]> git.lyx.org Git - lyx.git/blob - src/paragraph.C
Fixed compilation problems.
[lyx.git] / src / paragraph.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2000 The LyX Team. 
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation "lyxparagraph.h"
15 #endif
16
17 #include <algorithm>
18 #include <fstream>
19 #include <csignal>
20
21 #include "lyxparagraph.h"
22 #include "support/textutils.h"
23 #include "lyxrc.h"
24 #include "layout.h"
25 #include "tex-strings.h"
26 #include "buffer.h"
27 #include "bufferparams.h"
28 #include "support/FileInfo.h"
29 #include "support/LAssert.h"
30 #include "debug.h"
31 #include "LaTeXFeatures.h"
32 #include "insets/insetinclude.h"
33 #include "insets/insetbib.h"
34 #include "insets/insettext.h"
35 #include "support/filetools.h"
36 #include "lyx_gui_misc.h"
37 #include "texrow.h"
38 #include "support/lyxmanip.h"
39 #include "BufferView.h"
40 #include "encoding.h"
41 #include "ParameterStruct.h"
42
43 using std::ostream;
44 using std::endl;
45 using std::fstream;
46 using std::ios;
47 using std::lower_bound;
48 using std::upper_bound;
49 using std::reverse;
50
51 int tex_code_break_column = 72;  // needs non-zero initialization. set later.
52 // this is a bad idea, but how can LyXParagraph find its buffer to get
53 // parameters? (JMarc)
54
55 extern string bibitemWidest(Buffer const *);
56
57 // this is a minibuffer
58
59 namespace {
60
61 char minibuffer_char;
62 LyXFont minibuffer_font;
63 Inset * minibuffer_inset;
64
65 } // namespace anon
66
67
68 extern BufferView * current_view;
69
70 // Initialization of the counter for the paragraph id's,
71 // declared in lyxparagraph.h
72 unsigned int LyXParagraph::paragraph_id = 0;
73
74 // Initialize static member.
75 ShareContainer<LyXFont> LyXParagraph::FontTable::container;
76
77
78 LyXParagraph::LyXParagraph()
79 {
80         text.reserve(500); // is this number too big?
81         for (int i = 0; i < 10; ++i) setCounter(i , 0);
82         enumdepth = 0;
83         itemdepth = 0;
84         next_ = 0;
85         previous_ = 0;
86 #ifndef NEW_INSETS
87         footnoteflag = LyXParagraph::NO_FOOTNOTE;
88         footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
89 #endif
90
91         inset_owner = 0;
92         id_ = paragraph_id++;
93         bibkey = 0; // ale970302
94         Clear();
95 }
96
97
98 // This konstruktor inserts the new paragraph in a list.
99 LyXParagraph::LyXParagraph(LyXParagraph * par)
100 {
101         text.reserve(500);
102         par->fitToSize();
103         
104         for (int i = 0; i < 10; ++i) setCounter(i, 0);
105         enumdepth = 0;
106         itemdepth = 0;
107         // double linked list begin
108         next_ = par->next_;
109         if (next_)
110                 next_->previous_ = this;
111         previous_ = par;
112         previous_->next_ = this;
113         // end
114 #ifndef NEW_INSETS
115         footnoteflag = LyXParagraph::NO_FOOTNOTE;
116         footnotekind = LyXParagraph::FOOTNOTE;
117 #endif
118         inset_owner = 0;
119         id_ = paragraph_id++;
120
121         bibkey = 0; // ale970302        
122     
123         Clear();
124 }
125
126
127 void LyXParagraph::writeFile(Buffer const * buf, ostream & os,
128                              BufferParams const & bparams,
129                              char footflag, char dth) const
130 {
131 #ifndef NEW_INSETS
132         if (footnoteflag != LyXParagraph::NO_FOOTNOTE ||
133             !previous_
134             || previous_->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
135                 // The beginning or the end of a footnote environment?
136                 if (footflag != footnoteflag) {
137                         footflag = footnoteflag;
138                         if (footflag) {
139                                 os << "\n\\begin_float "
140                                    << string_footnotekinds[footnotekind]
141                                    << " ";
142                         } else {
143                                 os << "\n\\end_float ";
144                         }
145                 }
146 #endif
147                 // The beginning or end of a deeper (i.e. nested) area?
148                 if (dth != params.depth()) {
149                         if (params.depth() > dth) {
150                                 while (params.depth() > dth) {
151                                         os << "\n\\begin_deeper ";
152                                         ++dth;
153                                 }
154                         } else {
155                                 while (params.depth() < dth) {
156                                         os << "\n\\end_deeper ";
157                                         --dth;
158                                 }
159                         }
160                 }
161
162                 // First write the layout
163                 os << "\n\\layout "
164                    << textclasslist.NameOfLayout(bparams.textclass, layout)
165                    << "\n";
166
167                 // Maybe some vertical spaces.
168                 if (params.spaceTop().kind() != VSpace::NONE)
169                         os << "\\added_space_top "
170                            << params.spaceTop().asLyXCommand() << " ";
171                 if (params.spaceBottom().kind() != VSpace::NONE)
172                         os << "\\added_space_bottom "
173                            << params.spaceBottom().asLyXCommand() << " ";
174
175                 // Maybe the paragraph has special spacing
176                 params.spacing().writeFile(os, true);
177                 
178                 // The labelwidth string used in lists.
179                 if (!params.labelWidthString().empty())
180                         os << "\\labelwidthstring "
181                            << params.labelWidthString() << '\n';
182
183                 // Lines above or below?
184                 if (params.lineTop())
185                         os << "\\line_top ";
186                 if (params.lineBottom())
187                         os << "\\line_bottom ";
188
189                 // Pagebreaks above or below?
190                 if (params.pagebreakTop())
191                         os << "\\pagebreak_top ";
192                 if (params.pagebreakBottom())
193                         os << "\\pagebreak_bottom ";
194                         
195                 // Start of appendix?
196                 if (params.startOfAppendix())
197                         os << "\\start_of_appendix ";
198
199                 // Noindent?
200                 if (params.noindent())
201                         os << "\\noindent ";
202                         
203                 // Alignment?
204                 if (params.align() != LYX_ALIGN_LAYOUT) {
205                         int h = 0;
206                         switch (params.align()) {
207                         case LYX_ALIGN_LEFT: h = 1; break;
208                         case LYX_ALIGN_RIGHT: h = 2; break;
209                         case LYX_ALIGN_CENTER: h = 3; break;
210                         default: h = 0; break;
211                         }
212                         os << "\\align " << string_align[h] << " ";
213                 }
214 #ifndef NO_PEXTRA
215                 if (params.pextraType() != PEXTRA_NONE) {
216                         os << "\\pextra_type " << params.pextraType();
217                         if (params.pextraType() == PEXTRA_MINIPAGE) {
218                                 os << " \\pextra_alignment "
219                                    << params.pextraAlignment();
220                                 if (params.pextraHfill())
221                                         os << " \\pextra_hfill "
222                                            << params.pextraHfill();
223                                 if (params.pextraStartMinipage())
224                                         os << " \\pextra_start_minipage "
225                                            << params.pextraStartMinipage();
226                         }
227                         if (!params.pextraWidth().empty()) {
228                                 os << " \\pextra_width "
229                                    << VSpace(params.pextraWidth()).asLyXCommand();
230                         } else if (!params.pextraWidthp().empty()) {
231                                 os << " \\pextra_widthp "
232                                    << params.pextraWidthp();
233                         }
234                         os << '\n';
235                 }
236 #endif
237 #ifndef NEW_INSETS
238         } else {
239                 // Dummy layout. This means that a footnote ended.
240                 os << "\n\\end_float ";
241                 footflag = LyXParagraph::NO_FOOTNOTE;
242         }
243 #endif
244
245         // bibitem  ale970302
246         if (bibkey)
247                 bibkey->Write(buf, os);
248
249         LyXFont font1(LyXFont::ALL_INHERIT, bparams.language);
250
251         int column = 0;
252         for (size_type i = 0; i < size(); ++i) {
253                 if (!i) {
254                         os << "\n";
255                         column = 0;
256                 }
257                 
258                 // Write font changes
259                 LyXFont font2 = GetFontSettings(bparams, i);
260                 if (font2 != font1) {
261                         font2.lyxWriteChanges(font1, os);
262                         column = 0;
263                         font1 = font2;
264                 }
265
266                 value_type const c = GetChar(i);
267                 switch (c) {
268                 case META_INSET:
269                 {
270                         Inset const * inset = GetInset(i);
271                         if (inset)
272                                 if (inset->DirectWrite()) {
273                                         // international char, let it write
274                                         // code directly so it's shorter in
275                                         // the file
276                                         inset->Write(buf, os);
277                                 } else {
278                                         os << "\n\\begin_inset ";
279                                         inset->Write(buf, os);
280                                         os << "\n\\end_inset \n\n";
281                                         column = 0;
282                                 }
283                 }
284                 break;
285                 case META_NEWLINE: 
286                         os << "\n\\newline \n";
287                         column = 0;
288                         break;
289                 case META_HFILL: 
290                         os << "\n\\hfill \n";
291                         column = 0;
292                         break;
293                 case '\\':
294                         os << "\n\\backslash \n";
295                         column = 0;
296                         break;
297                 case '.':
298                         if (i + 1 < size() && GetChar(i + 1) == ' ') {
299                                 os << ".\n";
300                                 column = 0;
301                         } else
302                                 os << ".";
303                         break;
304                 default:
305                         if ((column > 70 && c == ' ')
306                             || column > 79) {
307                                 os << "\n";
308                                 column = 0;
309                         }
310                         // this check is to amend a bug. LyX sometimes
311                         // inserts '\0' this could cause problems.
312                         if (c != '\0')
313                                 os << c;
314                         else
315                                 lyxerr << "ERROR (LyXParagraph::writeFile):"
316                                         " NULL char in structure." << endl;
317                         ++column;
318                         break;
319                 }
320         }
321         
322         // now write the next paragraph
323         if (next_)
324                 next_->writeFile(buf, os, bparams, footflag, dth);
325 }
326
327
328 void LyXParagraph::validate(LaTeXFeatures & features) const
329 {
330         BufferParams const & bparams = features.bufferParams();
331
332 #ifndef NEW_INSETS
333         // this will be useful later
334         LyXLayout const & layout =
335                 textclasslist.Style(bparams.textclass, 
336                                     GetLayout());
337 #endif
338         
339         // check the params.
340         if (params.lineTop() || params.lineBottom())
341                 features.lyxline = true;
342         if (!params.spacing().isDefault())
343                 features.setspace = true;
344         
345         // then the layouts
346         features.layout[GetLayout()] = true;
347
348         // then the fonts
349         Language const * doc_language = bparams.language;
350         
351         for (FontList::const_iterator cit = fontlist.begin();
352              cit != fontlist.end(); ++cit) {
353                 if ((*cit).font().noun() == LyXFont::ON) {
354                         lyxerr[Debug::LATEX] << "font.noun: "
355                                              << (*cit).font().noun()
356                                              << endl;
357                         features.noun = true;
358                         lyxerr[Debug::LATEX] << "Noun enabled. Font: "
359                                              << (*cit).font().stateText(0)
360                                              << endl;
361                 }
362                 switch ((*cit).font().color()) {
363                 case LColor::none:
364                 case LColor::inherit:
365                 case LColor::ignore:
366                         break;
367                 default:
368                         features.color = true;
369                         lyxerr[Debug::LATEX] << "Color enabled. Font: "
370                                              << (*cit).font().stateText(0)
371                                              << endl;
372                 }
373
374                 Language const * language = (*cit).font().language();
375                 if (language->babel() != doc_language->babel()) {
376                         features.UsedLanguages.insert(language);
377                         lyxerr[Debug::LATEX] << "Found language "
378                                              << language->babel() << endl;
379                 }
380         }
381
382         // then the insets
383         for (InsetList::const_iterator cit = insetlist.begin();
384              cit != insetlist.end(); ++cit) {
385                 if ((*cit).inset)
386                         (*cit).inset->Validate(features);
387         }
388
389 #ifndef NO_PEXTRA
390         if (params.pextraType() == PEXTRA_INDENT)
391                 features.LyXParagraphIndent = true;
392         if (params.pextraType() == PEXTRA_FLOATFLT)
393                 features.floatflt = true;
394 #endif
395 #ifndef NEW_INSETS
396         if (layout.needprotect 
397             && next_ && next_->footnoteflag != LyXParagraph::NO_FOOTNOTE)
398                 features.NeedLyXFootnoteCode = true;
399 #endif
400 #ifndef NO_PEXTRA
401         if (bparams.paragraph_separation == BufferParams::PARSEP_INDENT
402             && params.pextraType() == LyXParagraph::PEXTRA_MINIPAGE)
403                 features.NeedLyXMinipageIndent = true;
404 #endif
405 #ifndef NEW_INSETS
406         if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
407                 features.algorithm = true;
408 #endif
409 }
410
411
412 // First few functions needed for cut and paste and paragraph breaking.
413 void LyXParagraph::CopyIntoMinibuffer(Buffer const & buffer,
414                                       LyXParagraph::size_type pos) const
415 {
416         BufferParams bparams = buffer.params;
417
418         minibuffer_char = GetChar(pos);
419         minibuffer_font = GetFontSettings(bparams, pos);
420         minibuffer_inset = 0;
421         if (minibuffer_char == LyXParagraph::META_INSET) {
422                 if (GetInset(pos)) {
423                         minibuffer_inset = GetInset(pos)->Clone(buffer);
424                 } else {
425                         minibuffer_inset = 0;
426                         minibuffer_char = ' ';
427                         // This reflects what GetInset() does (ARRae)
428                 }
429         }
430 }
431
432
433 void LyXParagraph::CutIntoMinibuffer(BufferParams const & bparams,
434                                      LyXParagraph::size_type pos)
435 {
436         minibuffer_char = GetChar(pos);
437         minibuffer_font = GetFontSettings(bparams, pos);
438         minibuffer_inset = 0;
439         if (minibuffer_char == LyXParagraph::META_INSET) {
440                 if (GetInset(pos)) {
441                         minibuffer_inset = GetInset(pos);
442                         // This is a little hack since I want exactly
443                         // the inset, not just a clone. Otherwise
444                         // the inset would be deleted when calling Erase(pos)
445                         // find the entry
446                         InsetTable search_elem(pos, 0);
447                         InsetList::iterator it =
448                                 lower_bound(insetlist.begin(),
449                                             insetlist.end(),
450                                             search_elem, matchIT());
451                         if (it != insetlist.end() && (*it).pos == pos)
452                                 (*it).inset = 0;
453                 } else {
454                         minibuffer_inset = 0;
455                         minibuffer_char = ' ';
456                         // This reflects what GetInset() does (ARRae)
457                 }
458
459         }
460
461         // Erase(pos); now the caller is responsible for that.
462 }
463
464
465 bool LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
466 {
467         if ((minibuffer_char == LyXParagraph::META_INSET) &&
468             !InsertInsetAllowed(minibuffer_inset))
469                 return false;
470         if (minibuffer_char == LyXParagraph::META_INSET)
471                 InsertInset(pos, minibuffer_inset, minibuffer_font);
472         else
473                 InsertChar(pos, minibuffer_char, minibuffer_font);
474         return true;
475 }
476
477 // end of minibuffer
478
479
480
481 void LyXParagraph::Clear()
482 {
483         params.clear();
484         
485         layout = 0;
486         bibkey = 0;
487 }
488
489
490 // the destructor removes the new paragraph from the list
491 LyXParagraph::~LyXParagraph()
492 {
493         if (previous_)
494                 previous_->next_ = next_;
495         if (next_)
496                 next_->previous_ = previous_;
497
498         for (InsetList::iterator it = insetlist.begin();
499              it != insetlist.end(); ++it) {
500                 delete (*it).inset;
501         }
502
503         // ale970302
504         delete bibkey;
505         //
506         //lyxerr << "LyXParagraph::paragraph_id = "
507         //       << LyXParagraph::paragraph_id << endl;
508 }
509
510
511 void LyXParagraph::Erase(LyXParagraph::size_type pos)
512 {
513 #ifndef NEW_INSETS
514         // > because last is the next unused position, and you can 
515         // use it if you want
516         if (pos > size()) {
517                 if (next_ && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
518                         NextAfterFootnote()->Erase(pos - text.size() - 1);
519                 else 
520                         lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
521                                 "position does not exist." << endl;
522                 return;
523         }
524 #else
525         Assert(pos < size());
526 #endif
527 #ifndef NEW_INSETS
528         if (pos < size()) { // last is free for insertation, but should be empty
529 #endif
530                 // if it is an inset, delete the inset entry 
531                 if (text[pos] == LyXParagraph::META_INSET) {
532                         // find the entry
533                         InsetTable search_inset(pos, 0);
534                         InsetList::iterator it =
535                                 lower_bound(insetlist.begin(),
536                                             insetlist.end(),
537                                             search_inset, matchIT());
538                         if (it != insetlist.end() && (*it).pos == pos) {
539                                 delete (*it).inset;
540                                 insetlist.erase(it);
541                         }
542                 }
543
544                 text.erase(text.begin() + pos);
545
546                 // Erase entries in the tables.
547                 FontTable search_font(pos, LyXFont());
548                 
549                 FontList::iterator it =
550                         lower_bound(fontlist.begin(),
551                                     fontlist.end(),
552                                     search_font, matchFT());
553                 if (it != fontlist.end() && (*it).pos() == pos &&
554                     (pos == 0 || 
555                      (it != fontlist.begin() && (*(it - 1)).pos() == pos - 1))) {
556                         // If it is a multi-character font
557                         // entry, we just make it smaller
558                         // (see update below), otherwise we
559                         // should delete it.
560                         unsigned int const i = it - fontlist.begin();
561                         fontlist.erase(fontlist.begin() + i);
562                         it = fontlist.begin() + i;
563                         if (i > 0 && i < fontlist.size() &&
564                             fontlist[i - 1].font() == fontlist[i].font()) {
565                                 fontlist.erase(fontlist.begin() + i - 1);
566                                 it = fontlist.begin() + i - 1;
567                         }
568                 }
569
570                 // Update all other entries.
571                 FontList::iterator fend = fontlist.end();
572                 for (; it != fend; ++it)
573                         (*it).pos((*it).pos() - 1);
574
575                 // Update the inset table.
576                 InsetTable search_inset(pos, 0);
577                 InsetList::iterator lend = insetlist.end();
578                 for (InsetList::iterator it =
579                              upper_bound(insetlist.begin(),
580                                          lend,
581                                          search_inset, matchIT());
582                      it != lend; ++it)
583                         --(*it).pos;
584 #ifndef NEW_INSETS
585         } else {
586                 lyxerr << "ERROR (LyXParagraph::Erase): "
587                         "can't erase non-existant char." << endl;
588         }
589 #endif
590 }
591
592
593 void LyXParagraph::InsertChar(LyXParagraph::size_type pos,
594                               LyXParagraph::value_type c)
595 {
596         LyXFont const f(LyXFont::ALL_INHERIT);
597         InsertChar(pos, c, f);
598 }
599
600
601 void LyXParagraph::InsertChar(LyXParagraph::size_type pos,
602                               LyXParagraph::value_type c,
603                               LyXFont const & font)
604 {
605 #ifndef NEW_INSETS
606         // > because last is the next unused position, and you can 
607         // use it if you want
608         if (pos > size()) {
609                 if (next_
610                     && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
611                         NextAfterFootnote()->InsertChar(pos - text.size() - 1,
612                                                         c);
613                 else 
614                         lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
615                                 "position does not exist." << endl;
616                 return;
617         }
618 #else
619         Assert(pos <= size());
620 #endif
621         text.insert(text.begin() + pos, c);
622
623         // Update the font table.
624         FontTable search_font(pos, LyXFont());
625         for (FontList::iterator it = lower_bound(fontlist.begin(),
626                                                  fontlist.end(),
627                                                  search_font, matchFT());
628              it != fontlist.end(); ++it)
629                 (*it).pos((*it).pos() + 1);
630    
631         // Update the inset table.
632         InsetTable search_inset(pos, 0);
633         for (InsetList::iterator it = lower_bound(insetlist.begin(),
634                                                   insetlist.end(),
635                                                   search_inset, matchIT());
636              it != insetlist.end(); ++it)
637                 ++(*it).pos;
638
639         SetFont(pos, font);
640 }
641
642
643 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
644                                Inset * inset)
645 {
646         LyXFont const f(LyXFont::ALL_INHERIT);
647         InsertInset(pos, inset, f);
648 }
649
650
651 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
652                                Inset * inset, LyXFont const & font)
653 {
654         Assert(inset);
655         
656 #ifndef NEW_INSETS
657         // > because last is the next unused position, and you can 
658         // use it if you want
659         if (pos > size()) {
660                 if (next_
661                     && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
662                         NextAfterFootnote()
663                                 ->InsertInset(pos - text.size() - 1,
664                                               inset, font);
665                 else
666                         lyxerr << "ERROR (LyXParagraph::InsertInset): " 
667                                 "position does not exist: " << pos << endl;
668                 return;
669         }
670 #else
671         Assert(pos <= size());
672 #endif
673         
674         InsertChar(pos, META_INSET, font);
675         Assert(text[pos] == META_INSET);
676         
677         // Add a new entry in the inset table.
678         InsetTable search_inset(pos, 0);
679         InsetList::iterator it = lower_bound(insetlist.begin(),
680                                              insetlist.end(),
681                                              search_inset, matchIT());
682         if (it != insetlist.end() && (*it).pos == pos)
683                 lyxerr << "ERROR (LyXParagraph::InsertInset): "
684                         "there is an inset in position: " << pos << endl;
685         else
686                 insetlist.insert(it, InsetTable(pos, inset));
687         if (inset_owner)
688                 inset->setOwner(inset_owner);
689 }
690
691
692 bool LyXParagraph::InsertInsetAllowed(Inset * inset)
693 {
694         //lyxerr << "LyXParagraph::InsertInsetAllowed" << endl;
695         
696         if (inset_owner)
697                 return inset_owner->InsertInsetAllowed(inset);
698         return true;
699 }
700
701
702 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
703 {
704 #ifndef NEW_INSETS
705         if (pos >= size()) {
706                 if (next_
707                     && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
708                         return NextAfterFootnote()
709                                 ->GetInset(pos - text.size() - 1);
710                 else
711                         lyxerr << "ERROR (LyXParagraph::GetInset): "
712                                 "position does not exist: "
713                                << pos << endl;
714                 
715                 return 0;
716         }
717 #else
718         Assert(pos < size());
719 #endif
720         // Find the inset.
721         InsetTable search_inset(pos, 0);
722         InsetList::iterator it = lower_bound(insetlist.begin(),
723                                              insetlist.end(),
724                                              search_inset, matchIT());
725         if (it != insetlist.end() && (*it).pos == pos)
726                 return (*it).inset;
727
728         lyxerr << "ERROR (LyXParagraph::GetInset): "
729                 "Inset does not exist: " << pos << endl;
730         //::raise(SIGSTOP);
731         
732         // text[pos] = ' '; // WHY!!! does this set the pos to ' '????
733         // Did this commenting out introduce a bug? So far I have not
734         // see any, please enlighten me. (Lgb)
735         // My guess is that since the inset does not exist, we might
736         // as well replace it with a space to prevent craches. (Asger)
737         return 0;
738 }
739
740
741 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
742 {
743 #ifndef NEW_INSETS
744         if (pos >= size()) {
745                 if (next_
746                     && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
747                         return NextAfterFootnote()
748                                 ->GetInset(pos - text.size() - 1);
749                 else
750                         lyxerr << "ERROR (LyXParagraph::GetInset): "
751                                 "position does not exist: "
752                                << pos << endl;
753
754                 return 0;
755         }
756 #else
757         Assert(pos < size());
758 #endif
759         // Find the inset.
760         InsetTable search_inset(pos, 0);
761         InsetList::const_iterator cit = lower_bound(insetlist.begin(),
762                                                     insetlist.end(),
763                                                     search_inset, matchIT());
764         if (cit != insetlist.end() && (*cit).pos == pos)
765                 return (*cit).inset;
766
767         lyxerr << "ERROR (LyXParagraph::GetInset): "
768                 "Inset does not exist: " << pos << endl;
769         //::raise(SIGSTOP);
770         //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
771         // Did this commenting out introduce a bug? So far I have not
772         // see any, please enlighten me. (Lgb)
773         // My guess is that since the inset does not exist, we might
774         // as well replace it with a space to prevent craches. (Asger)
775         return 0;
776 }
777
778
779 // Gets uninstantiated font setting at position.
780 // Optimized after profiling. (Asger)
781 LyXFont const LyXParagraph::GetFontSettings(BufferParams const & bparams,
782                                       LyXParagraph::size_type pos) const
783 {
784 #ifdef NEW_INSETS
785         Assert(pos <= size());
786 #endif
787 #ifndef NEW_INSETS
788         if (pos < size()) {
789 #endif
790                 FontTable search_font(pos, LyXFont());
791                 FontList::const_iterator cit = lower_bound(fontlist.begin(),
792                                                     fontlist.end(),
793                                                     search_font, matchFT());
794                 if (cit != fontlist.end())
795                         return (*cit).font();
796 #ifndef NEW_INSETS
797         }
798 #endif
799 #ifndef NEW_INSETS
800         // > because last is the next unused position, and you can 
801         // use it if you want
802         else if (pos > size()) {
803                 if (next_
804                     && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
805                         return NextAfterFootnote()
806                                 ->GetFontSettings(bparams,
807                                                   pos - text.size() - 1);
808                 else
809                         // Why is it an error to ask for the font of a
810                         // position that does not exist? Would it be
811                         // enough for this to be enabled on debug?
812                         // We want strict error checking, but it's ok to only
813                         // have it when debugging. (Asger)
814                         lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
815                                 "position does not exist. "
816                                << pos << " (" << static_cast<int>(pos)
817                                << ")" << endl;
818         } else if (pos > 0) {
819                 return GetFontSettings(bparams, pos - 1);
820         }
821 #else
822         if (pos == size() && size())
823                 return GetFontSettings(bparams, pos - 1);
824 #endif
825         //else
826         // pos = size() = 0
827         return LyXFont(LyXFont::ALL_INHERIT, getParLanguage(bparams));
828
829         //return LyXFont(LyXFont::ALL_INHERIT);
830 }
831
832
833 // Gets uninstantiated font setting at position 0
834 LyXFont const LyXParagraph::GetFirstFontSettings() const
835 {
836         if (size() > 0) {
837                 if (!fontlist.empty())
838                         return fontlist[0].font();
839         }
840         
841 #ifndef NEW_INSETS
842         else if (next_ && next_->footnoteflag != LyXParagraph::NO_FOOTNOTE) 
843                 return NextAfterFootnote()->GetFirstFontSettings();
844 #endif
845         return LyXFont(LyXFont::ALL_INHERIT);
846 }
847
848
849 // Gets the fully instantiated font at a given position in a paragraph
850 // This is basically the same function as LyXText::GetFont() in text2.C.
851 // The difference is that this one is used for generating the LaTeX file,
852 // and thus cosmetic "improvements" are disallowed: This has to deliver
853 // the true picture of the buffer. (Asger)
854 // If position is -1, we get the layout font of the paragraph.
855 // If position is -2, we get the font of the manual label of the paragraph.
856 LyXFont const LyXParagraph::getFont(BufferParams const & bparams,
857                               LyXParagraph::size_type pos) const
858 {
859         LyXFont tmpfont;
860         LyXLayout const & layout =
861                 textclasslist.Style(bparams.textclass, 
862                                     GetLayout());
863         LyXParagraph::size_type main_body = 0;
864         if (layout.labeltype == LABEL_MANUAL)
865                 main_body = BeginningOfMainBody();
866
867         if (pos >= 0) {
868                 LyXFont layoutfont;
869                 if (pos < main_body)
870                         layoutfont = layout.labelfont;
871                 else
872                         layoutfont = layout.font;
873                 tmpfont = GetFontSettings(bparams, pos);
874                 tmpfont.realize(layoutfont);
875         } else {
876                 // process layoutfont for pos == -1 and labelfont for pos < -1
877                 if (pos == -1)
878                         tmpfont = layout.font;
879                 else
880                         tmpfont = layout.labelfont;
881                 tmpfont.setLanguage(getParLanguage(bparams));
882         }
883
884         // check for environment font information
885         char par_depth = GetDepth();
886         LyXParagraph const * par = this;
887         while (par && par_depth && !tmpfont.resolved()) {
888                 par = par->DepthHook(par_depth - 1);
889                 if (par) {
890                         tmpfont.realize(textclasslist.
891                                         Style(bparams.textclass,
892                                               par->GetLayout()).font);
893                         par_depth = par->GetDepth();
894                 }
895         }
896
897         tmpfont.realize(textclasslist
898                         .TextClass(bparams.textclass)
899                         .defaultfont());
900         return tmpfont;
901 }
902
903
904 /// Returns the height of the highest font in range
905 LyXFont::FONT_SIZE
906 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
907                                  LyXParagraph::size_type endpos) const
908 {
909         LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
910         if (fontlist.empty())
911                 return maxsize;
912
913         FontTable end_search(endpos, LyXFont());
914         FontList::const_iterator end_it = lower_bound(fontlist.begin(),
915                                                       fontlist.end(),
916                                                       end_search, matchFT());
917         if (end_it != fontlist.end())
918                 ++end_it;
919
920         FontTable start_search(startpos, LyXFont());
921         for (FontList::const_iterator cit =
922                      lower_bound(fontlist.begin(),
923                                  fontlist.end(),
924                                  start_search, matchFT());
925              cit != end_it; ++cit) {
926                 LyXFont::FONT_SIZE size = (*cit).font().size();
927                 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
928                         maxsize = size;
929         }
930         return maxsize;
931 }
932
933
934 LyXParagraph::value_type
935 LyXParagraph::GetChar(LyXParagraph::size_type pos) const
936 {
937 #ifndef NEW_INSETS
938         Assert(pos >= 0);
939 #else
940         Assert(pos <= size());
941         if (!size() || pos == size()) return '\0';
942 #endif
943
944 #ifndef NEW_INSETS
945         if (pos < size()) {
946 #endif
947                 return text[pos];
948 #ifndef NEW_INSETS
949         }
950 #endif
951 #ifndef NEW_INSETS
952         // > because last is the next unused position, and you can 
953         // use it if you want
954         else if (pos > size()) {
955                 if (next_ && next_->footnoteflag != LyXParagraph::NO_FOOTNOTE) 
956                         return NextAfterFootnote()
957                                 ->GetChar(pos - text.size() - 1);
958                 else
959                         {
960                         lyxerr << "ERROR (LyXParagraph::GetChar const): "
961                                 "position does not exist."
962                                << pos << " (" << static_cast<int>(pos)
963                                << ")\n";
964                         Assert(false);
965                 }
966                 return '\0';
967         } else {
968                 // We should have a footnote environment.
969                 if (!next_ || next_->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
970                         // Notice that LyX does request the
971                         // last char from time to time. (Asger)
972                         //lyxerr << "ERROR (LyXParagraph::GetChar): "
973                         //      "expected footnote." << endl;
974                         return '\0';
975                 }
976                 switch (next_->footnotekind) {
977                 case LyXParagraph::FOOTNOTE:
978                         return LyXParagraph::META_FOOTNOTE;
979                 case LyXParagraph::MARGIN:
980                         return LyXParagraph::META_MARGIN;
981                 case LyXParagraph::FIG:
982                 case LyXParagraph::WIDE_FIG:
983                         return LyXParagraph::META_FIG;
984                 case LyXParagraph::TAB:
985                 case LyXParagraph::WIDE_TAB:
986                         return LyXParagraph::META_TAB;
987                 case LyXParagraph::ALGORITHM:
988                         return LyXParagraph::META_ALGORITHM;
989                 }
990                 return '\0'; // to shut up gcc
991         }
992 #endif
993 }
994
995
996 LyXParagraph::value_type
997 LyXParagraph::GetUChar(BufferParams const & bparams,
998                        LyXParagraph::size_type pos) const
999 {
1000         value_type c = GetChar(pos);
1001         if (!lyxrc.rtl_support)
1002                 return c;
1003
1004         value_type uc = c;
1005         switch (c) {
1006         case '(':
1007                 uc = ')';
1008                 break;
1009         case ')':
1010                 uc = '(';
1011                 break;
1012         case '[':
1013                 uc = ']';
1014                 break;
1015         case ']':
1016                 uc = '[';
1017                 break;
1018         case '{':
1019                 uc = '}';
1020                 break;
1021         case '}':
1022                 uc = '{';
1023                 break;
1024         case '<':
1025                 uc = '>';
1026                 break;
1027         case '>':
1028                 uc = '<';
1029                 break;
1030         }
1031         if (uc != c && GetFontSettings(bparams, pos).isRightToLeft())
1032                 return uc;
1033         else
1034                 return c;
1035 }
1036
1037 // return an string of the current word, and the end of the word in lastpos.
1038 string const LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
1039 {
1040         Assert(lastpos >= 0);
1041
1042         // the current word is defined as starting at the first character
1043         // from the immediate left of lastpospos which meets the definition
1044         // of IsLetter(), continuing to the last character to the right
1045         // of this meeting IsLetter.
1046
1047         string theword;
1048
1049         // grab a word
1050                 
1051         // move back until we have a letter
1052
1053         //there's no real reason to have firstpos & lastpos as
1054         //separate variables as this is written, but maybe someon
1055         // will want to return firstpos in the future.
1056
1057         //since someone might have typed a punctuation first
1058         int firstpos = lastpos;
1059         
1060         while ((firstpos >= 0) && !IsLetter(firstpos))
1061                 --firstpos;
1062
1063         // now find the beginning by looking for a nonletter
1064         
1065         while ((firstpos>= 0) && IsLetter(firstpos))
1066                 --firstpos;
1067
1068         // the above is now pointing to the preceeding non-letter
1069         ++firstpos;
1070         lastpos = firstpos;
1071
1072         // so copy characters into theword  until we get a nonletter
1073         // note that this can easily exceed lastpos, wich means
1074         // that if used in the middle of a word, the whole word
1075         // is included
1076
1077         while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1078         
1079         return theword;
1080
1081 }
1082
1083
1084 #ifndef NEW_INSETS
1085 LyXParagraph::size_type LyXParagraph::Last() const
1086 {
1087         if (next_ && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1088                 return text.size() + NextAfterFootnote()->Last() + 1;
1089         // the 1 is the symbol
1090         // for the footnote
1091         else
1092                 return text.size();
1093 }
1094 #endif
1095
1096
1097 #ifndef NEW_INSETS
1098 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
1099 {
1100         // > because last is the next unused position, and you can 
1101         // use it if you want
1102         if (pos > size()) {
1103                 if (next_
1104                     && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
1105                         return NextAfterFootnote()
1106                                 ->ParFromPos(pos - text.size() - 1);
1107                 else
1108                         lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1109                                 "position does not exist." << endl;
1110                 return this;
1111         } else
1112                 return this;
1113 }
1114 #endif
1115
1116
1117 #ifndef NEW_INSETS
1118 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1119 {
1120         // > because last is the next unused position, and you can 
1121         // use it if you want
1122         if (pos > size()) {
1123                 if (next_
1124                     && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
1125                         return NextAfterFootnote()
1126                                 ->PositionInParFromPos(pos - text.size() - 1);
1127                 else
1128                         lyxerr <<
1129                                 "ERROR (LyXParagraph::PositionInParFromPos): "
1130                                 "position does not exist." << endl;
1131                 return pos;
1132         }
1133         else
1134                 return pos;
1135 }
1136 #endif
1137
1138
1139 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1140                            LyXFont const & font)
1141 {
1142 #ifndef NEW_INSETS
1143         // > because last is the next unused position, and you can 
1144         // use it if you want
1145         if (pos > size()) {
1146                 if (next_ &&
1147                     next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1148                         NextAfterFootnote()->SetFont(pos - text.size() - 1,
1149                                                      font);
1150                 } else
1151                         lyxerr << "ERROR (LyXParagraph::SetFont): "
1152                                 "position does not exist." << endl;
1153                 
1154                 return;
1155         }
1156 #else
1157         Assert(pos <= size());
1158 #endif
1159
1160         // First, reduce font against layout/label font
1161         // Update: The SetCharFont() routine in text2.C already
1162         // reduces font, so we don't need to do that here. (Asger)
1163         // No need to simplify this because it will disappear
1164         // in a new kernel. (Asger)
1165         // Next search font table
1166
1167         FontTable search_font(pos, LyXFont());
1168         FontList::iterator it = lower_bound(fontlist.begin(),
1169                                             fontlist.end(),
1170                                             search_font, matchFT());
1171         unsigned int i = it - fontlist.begin();
1172         bool notfound = it == fontlist.end();
1173
1174         if (!notfound && fontlist[i].font() == font)
1175                 return;
1176
1177         bool begin = pos == 0 || notfound ||
1178                 (i > 0 && fontlist[i-1].pos() == pos - 1);
1179         // Is position pos is a beginning of a font block?
1180         bool end = !notfound && fontlist[i].pos() == pos;
1181         // Is position pos is the end of a font block?
1182         if (begin && end) { // A single char block
1183                 if (i + 1 < fontlist.size() &&
1184                     fontlist[i + 1].font() == font) {
1185                         // Merge the singleton block with the next block
1186                         fontlist.erase(fontlist.begin() + i);
1187                         if (i > 0 && fontlist[i - 1].font() == font)
1188                                 fontlist.erase(fontlist.begin() + i-1);
1189                 } else if (i > 0 && fontlist[i - 1].font() == font) {
1190                         // Merge the singleton block with the previous block
1191                         fontlist[i - 1].pos(pos);
1192                         fontlist.erase(fontlist.begin() + i);
1193                 } else
1194                         fontlist[i].font(font);
1195         } else if (begin) {
1196                 if (i > 0 && fontlist[i - 1].font() == font)
1197                         fontlist[i - 1].pos(pos);
1198                 else
1199                         fontlist.insert(fontlist.begin() + i,
1200                                         FontTable(pos, font));
1201         } else if (end) {
1202                 fontlist[i].pos(pos - 1);
1203                 if (!(i + 1 < fontlist.size() &&
1204                       fontlist[i + 1].font() == font))
1205                         fontlist.insert(fontlist.begin() + i + 1,
1206                                         FontTable(pos, font));
1207         } else { // The general case. The block is splitted into 3 blocks
1208                 fontlist.insert(fontlist.begin() + i, 
1209                                 FontTable(pos - 1, fontlist[i].font()));
1210                 fontlist.insert(fontlist.begin() + i + 1,
1211                                 FontTable(pos, font));
1212         }
1213 }
1214
1215
1216
1217 void LyXParagraph::next(LyXParagraph * p)
1218 {
1219         next_ = p;
1220 }
1221
1222
1223 // This function is able to hide closed footnotes.
1224 LyXParagraph * LyXParagraph::next()
1225 {
1226 #ifndef NEW_INSETS
1227         if (next_ && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1228                 LyXParagraph * tmp = next_;
1229                 while (tmp
1230                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1231                         tmp = tmp->next_;
1232                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1233                         return tmp->next(); /* there can be more than one
1234                                                footnote in a logical
1235                                                paragraph */
1236                 else
1237                         return next_;  // This should never happen!
1238         } else
1239 #endif
1240                 return next_;
1241 }
1242
1243
1244 LyXParagraph const * LyXParagraph::next() const
1245 {
1246 #ifndef NEW_INSETS
1247         if (next_ && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1248                 LyXParagraph * tmp = next_;
1249                 while (tmp
1250                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1251                         tmp = tmp->next_;
1252                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1253                         return tmp->next(); /* there can be more than one
1254                                                footnote in a logical
1255                                                paragraph */
1256                 else
1257                         return next_;  // This should never happen!
1258         } else
1259 #endif
1260                 return next_;
1261 }
1262
1263
1264 #ifndef NEW_INSETS
1265 LyXParagraph * LyXParagraph::NextAfterFootnote()
1266 {
1267         if (next_ && next_->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1268                 LyXParagraph * tmp = next_;
1269                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1270                         tmp = tmp->next_;
1271                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1272                         return tmp;   /* there can be more than one footnote
1273                                          in a logical paragraph */
1274                 else
1275                         return next_;  // This should never happen!
1276         } else
1277                 return next_;
1278 }
1279 #endif
1280
1281
1282 #ifndef NEW_INSETS
1283 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1284 {
1285         if (next_ && next_->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1286                 LyXParagraph * tmp = next_;
1287                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1288                         tmp = tmp->next_;
1289                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1290                         return tmp;   /* there can be more than one footnote
1291                                          in a logical paragraph */
1292                 else
1293                         return next_;  // This should never happen!
1294         } else
1295                 return next_;
1296 }
1297 #endif
1298
1299
1300 #ifndef NEW_INSETS
1301 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1302 {
1303         LyXParagraph * tmp;
1304         if (previous_ && previous_->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1305                 tmp = previous_;
1306                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1307                         tmp = tmp->previous_;
1308                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1309                         return tmp;    /* there can be more than one footnote
1310                                           in a logical paragraph */
1311                 else
1312                         return previous_;  // This should never happen!
1313         } else
1314                 return previous_;
1315 }
1316 #endif
1317
1318
1319 #ifndef NEW_INSETS
1320 LyXParagraph * LyXParagraph::LastPhysicalPar()
1321 {
1322         if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1323                 return this;
1324    
1325         LyXParagraph * tmp = this;
1326         while (tmp->next_
1327                && tmp->next_->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1328                 tmp = tmp->NextAfterFootnote();
1329    
1330         return tmp;
1331 }
1332 #endif
1333
1334
1335 #ifndef NEW_INSETS
1336 LyXParagraph const * LyXParagraph::LastPhysicalPar() const
1337 {
1338         if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1339                 return this;
1340    
1341         LyXParagraph const * tmp = this;
1342         while (tmp->next_
1343                && tmp->next_->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1344                 tmp = tmp->NextAfterFootnote();
1345    
1346         return tmp;
1347 }
1348 #endif
1349
1350
1351 #ifndef NEW_INSETS
1352 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1353 {
1354         if (!IsDummy())
1355                 return this;
1356         LyXParagraph * tmppar = this;
1357
1358         while (tmppar &&
1359                (tmppar->IsDummy()
1360                 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1361                 tmppar = tmppar->previous_;
1362    
1363         if (!tmppar) {
1364                 return this;
1365         } else
1366                 return tmppar;
1367 }
1368 #endif
1369
1370
1371 #ifndef NEW_INSETS
1372 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1373 {
1374         if (!IsDummy())
1375                 return this;
1376         LyXParagraph const * tmppar = this;
1377
1378         while (tmppar &&
1379                (tmppar->IsDummy()
1380                 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1381                 tmppar = tmppar->previous_;
1382    
1383         if (!tmppar) {
1384                 return this;
1385         } else
1386                 return tmppar;
1387 }
1388 #endif
1389
1390
1391 void LyXParagraph::previous(LyXParagraph * p)
1392 {
1393         previous_ = p;
1394 }
1395
1396
1397 // This function is able to hide closed footnotes.
1398 LyXParagraph * LyXParagraph::previous()
1399 {
1400 #ifndef NEW_INSETS
1401         LyXParagraph * tmp = previous_;
1402         if (!tmp)
1403                 return tmp;
1404
1405         if (tmp->previous_
1406             && tmp->previous_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1407                 tmp = tmp->previous_;
1408                 while (tmp
1409                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1410                         tmp = tmp->previous_;
1411                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1412                         return tmp->next_->previous();  
1413
1414                 else
1415                         return previous_; 
1416         } else
1417 #endif
1418                 return previous_;
1419 }
1420
1421
1422 // This function is able to hide closed footnotes.
1423 LyXParagraph const * LyXParagraph::previous() const
1424 {
1425 #ifndef NEW_INSETS
1426         LyXParagraph * tmp = previous_;
1427         if (!tmp)
1428                 return tmp;
1429         if (tmp->previous_
1430             && tmp->previous_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1431                 tmp = tmp->previous_;
1432                 while (tmp
1433                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1434                         tmp = tmp->previous_;
1435                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1436                         return tmp->next_->previous();  
1437
1438                 else
1439                         return previous_;
1440         } else
1441 #endif
1442                 return previous_;
1443 }
1444
1445
1446 void LyXParagraph::BreakParagraph(BufferParams const & bparams,
1447                                   LyXParagraph::size_type pos,
1448                                   int flag)
1449 {
1450         size_type i;
1451         size_type j;
1452         // create a new paragraph
1453 #ifndef NEW_INSETS
1454         size_type pos_end;
1455         size_type pos_first;
1456         LyXParagraph * par = ParFromPos(pos);
1457         LyXParagraph * firstpar = FirstPhysicalPar();
1458    
1459         LyXParagraph * tmp = new LyXParagraph(par);
1460 #else
1461         //LyXParagraph * par = this;
1462         //LyXParagraph * firstpar = this;
1463         LyXParagraph * tmp = new LyXParagraph(this);
1464 #endif
1465
1466 #ifndef NEW_INSETS
1467         tmp->footnoteflag = footnoteflag;
1468         tmp->footnotekind = footnotekind;
1469 #endif
1470         // this is an idea for a more userfriendly layout handling, I will
1471         // see what the users say
1472
1473 #ifndef NEW_INSETS
1474         // layout stays the same with latex-environments
1475         if (flag) {
1476                 tmp->SetOnlyLayout(bparams, firstpar->layout);
1477                 tmp->SetLabelWidthString(firstpar->params.labelWidthString());
1478         }
1479 #else
1480         // layout stays the same with latex-environments
1481         if (flag) {
1482                 tmp->SetOnlyLayout(bparams, layout);
1483                 tmp->SetLabelWidthString(params.labelWidthString());
1484         }
1485 #endif
1486 #ifndef NEW_INSETS
1487         if (Last() > pos || !Last() || flag == 2) {
1488                 tmp->SetOnlyLayout(bparams, firstpar->layout);
1489                 tmp->params.align(firstpar->params.align());
1490                 tmp->SetLabelWidthString(firstpar->params.labelWidthString());
1491       
1492                 tmp->params.lineBottom(firstpar->params.lineBottom());
1493                 firstpar->params.lineBottom(false);
1494                 tmp->params.pagebreakBottom(firstpar->params.pagebreakBottom());
1495                 firstpar->params.pagebreakBottom(false);
1496                 tmp->params.spaceBottom(firstpar->params.spaceBottom());
1497                 firstpar->params.spaceBottom(VSpace(VSpace::NONE));
1498       
1499                 tmp->params.depth(firstpar->params.depth());
1500                 tmp->params.noindent(firstpar->params.noindent());
1501 #else
1502         if (size() > pos || !size() || flag == 2) {
1503                 tmp->SetOnlyLayout(bparams, layout);
1504                 tmp->params.align(params.align());
1505                 tmp->SetLabelWidthString(params.labelWidthString());
1506       
1507                 tmp->params.lineBottom(params.lineBottom());
1508                 params.lineBottom(false);
1509                 tmp->params.pagebreakBottom(params.pagebreakBottom());
1510                 params.pagebreakBottom(false);
1511                 tmp->params.spaceBottom(params.spaceBottom());
1512                 params.spaceBottom(VSpace(VSpace::NONE));
1513       
1514                 tmp->params.depth(params.depth());
1515                 tmp->params.noindent(params.noindent());
1516 #endif
1517                 // copy everything behind the break-position
1518                 // to the new paragraph
1519 #ifndef NEW_INSETS
1520                 pos_first = 0;
1521                 while (ParFromPos(pos_first) != par)
1522                         ++pos_first;
1523                 pos_end = pos_first + par->text.size() - 1;
1524
1525
1526                 for (i = j = pos; i <= pos_end; ++i) {
1527                         par->CutIntoMinibuffer(bparams, i - pos_first);
1528                         if (tmp->InsertFromMinibuffer(j - pos))
1529                                 ++j;
1530                 }
1531
1532                 tmp->fitToSize();
1533
1534                 for (i = pos_end; i >= pos; --i)
1535                         par->Erase(i - pos_first);
1536
1537                 par->fitToSize();
1538 #else
1539                 size_type pos_end = text.size() - 1;
1540                 
1541                 for (i = j = pos; i <= pos_end; ++i) {
1542                         CutIntoMinibuffer(bparams, i);
1543                         if (tmp->InsertFromMinibuffer(j - pos))
1544                                 ++j;
1545                 }
1546                 tmp->fitToSize();
1547                 for (i = pos_end; i >= pos; --i)
1548                         Erase(i);
1549
1550                 fitToSize();
1551 #endif
1552         }
1553
1554 #ifndef NEW_INSETS
1555         // just an idea of me
1556         if (!pos) {
1557                 tmp->params.lineTop(firstpar->params.lineTop());
1558                 tmp->params.pagebreakTop(firstpar->params.pagebreakTop());
1559                 tmp->params.spaceTop(firstpar->params.spaceTop());
1560                 tmp->bibkey = firstpar->bibkey;
1561                 firstpar->Clear();
1562                 // layout stays the same with latex-environments
1563                 if (flag) {
1564                         firstpar->SetOnlyLayout(bparams, tmp->layout);
1565                         firstpar->SetLabelWidthString(tmp->params.labelWidthString());
1566                         firstpar->params.depth(tmp->params.depth());
1567                 }
1568         }
1569 #else
1570         // just an idea of me
1571         if (!pos) {
1572                 tmp->params.lineTop(params.lineTop());
1573                 tmp->params.pagebreakTop(params.pagebreakTop());
1574                 tmp->params.spaceTop(params.spaceTop());
1575                 tmp->bibkey = bibkey;
1576                 Clear();
1577                 // layout stays the same with latex-environments
1578                 if (flag) {
1579                         SetOnlyLayout(bparams, tmp->layout);
1580                         SetLabelWidthString(tmp->params.labelWidthString());
1581                         params.depth(tmp->params.depth());
1582                 }
1583         }
1584 #endif
1585 }
1586
1587
1588 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1589 {
1590 #ifndef NEW_INSETS
1591         par = par->FirstPhysicalPar();
1592         footnoteflag = par->footnoteflag;
1593         footnotekind = par->footnotekind;
1594 #endif
1595         layout = par->layout;
1596         params.makeSame(par->params);
1597         
1598         // This can be changed after NEW_INSETS is in effect. (Lgb)
1599         SetLabelWidthString(par->params.labelWidthString());
1600 }
1601
1602
1603 #ifndef NEW_INSETS
1604 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1605 {
1606         LyXParagraph * tmppar = this;
1607         while (tmppar && (
1608                 (tmppar->IsDummy()
1609                  && tmppar->previous_->footnoteflag == 
1610                  LyXParagraph::CLOSED_FOOTNOTE)
1611                 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1612                 tmppar = tmppar->previous_;
1613    
1614         if (!tmppar)
1615                 return this;  // This should never happen!
1616         else
1617                 return tmppar;
1618 }
1619 #endif
1620
1621
1622 int LyXParagraph::StripLeadingSpaces(LyXTextClassList::size_type tclass) 
1623 {
1624         if (textclasslist.Style(tclass, GetLayout()).free_spacing)
1625                 return 0;
1626         
1627         int i = 0;
1628 #ifndef NEW_INSETS
1629         if (!IsDummy()) {
1630                 while (Last()
1631 #else
1632                 while (size()
1633 #endif
1634                        && (IsNewline(0) || IsLineSeparator(0))){
1635                         Erase(0);
1636                         ++i;
1637                 }
1638 #ifndef NEW_INSETS
1639         }
1640 #endif
1641         return i;
1642 }
1643
1644
1645 LyXParagraph * LyXParagraph::Clone() const
1646 {
1647         // create a new paragraph
1648         LyXParagraph * result = new LyXParagraph;
1649    
1650         result->MakeSameLayout(this);
1651
1652         // this is because of the dummy layout of the paragraphs that
1653         // follow footnotes
1654         result->layout = layout;
1655
1656         result->inset_owner = inset_owner;
1657    
1658         // ale970302
1659         if (bibkey)
1660                 result->bibkey = static_cast<InsetBibKey *>
1661                                  (bibkey->Clone(*current_view->buffer()));
1662         else
1663                 result->bibkey = 0;
1664     
1665         // copy everything behind the break-position to the new paragraph
1666
1667         result->text = text;
1668         result->fontlist = fontlist;
1669         result->insetlist = insetlist;
1670         for (InsetList::iterator it = result->insetlist.begin();
1671              it != result->insetlist.end(); ++it)
1672                 (*it).inset = (*it).inset->Clone(*current_view->buffer());
1673         return result;
1674 }
1675
1676
1677 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1678 {
1679 #ifndef NEW_INSETS
1680         par = par->FirstPhysicalPar();
1681 #endif
1682
1683         return 
1684 #ifndef NEW_INSETS
1685                 par->footnoteflag == footnoteflag &&
1686                 par->footnotekind == footnotekind &&
1687 #endif
1688                 par->layout == layout &&
1689                 params.sameLayout(par->params);
1690 }
1691
1692
1693 void LyXParagraph::BreakParagraphConservative(BufferParams const & bparams,
1694                                               LyXParagraph::size_type pos)
1695 {
1696 #ifndef NEW_INSETS
1697         // create a new paragraph
1698         LyXParagraph * par = ParFromPos(pos);
1699
1700         LyXParagraph * tmp = new LyXParagraph(par);
1701    
1702         tmp->MakeSameLayout(par);
1703
1704         // When can pos < Last()?
1705         // I guess pos == Last() is possible.
1706         if (Last() > pos) {
1707                 // copy everything behind the break-position to the new
1708                 // paragraph
1709                 size_type pos_first = 0;
1710                 while (ParFromPos(pos_first) != par)
1711                         ++pos_first;
1712                 size_type pos_end = pos_first + par->text.size() - 1;
1713
1714                 size_type i, j;
1715                 for (i = j = pos; i <= pos_end; ++i) {
1716                         par->CutIntoMinibuffer(bparams, i - pos_first);
1717                         if (tmp->InsertFromMinibuffer(j - pos))
1718                                 ++j;
1719                 }
1720
1721                 tmp->fitToSize();
1722
1723                 for (size_type i = pos_end; i >= pos; --i)
1724                         par->Erase(i - pos_first);
1725
1726                 par->fitToSize();
1727         }
1728 #else
1729         // create a new paragraph
1730         LyXParagraph * tmp = new LyXParagraph(this);
1731         tmp->MakeSameLayout(this);
1732
1733         // When can pos > Last()?
1734         // I guess pos == Last() is possible.
1735         if (size() > pos) {
1736                 // copy everything behind the break-position to the new
1737                 // paragraph
1738                 size_type pos_end = text.size() - 1;
1739
1740                 size_type i, j;
1741                 for (i = j = pos; i <= pos_end; ++i) {
1742                         CutIntoMinibuffer(bparams, i);
1743                         if (tmp->InsertFromMinibuffer(j - pos))
1744                                 ++j;
1745                 }
1746
1747                 tmp->fitToSize();
1748                 
1749                 for (size_type i = pos_end; i >= pos; --i)
1750                         Erase(i);
1751
1752                 fitToSize();
1753         }
1754 #endif
1755 }
1756    
1757
1758 // Be carefull, this does not make any check at all.
1759 // This method has wrong name, it combined this par with the next par.
1760 // In that sense it is the reverse of break paragraph. (Lgb)
1761 void LyXParagraph::PasteParagraph(BufferParams const & bparams)
1762 {
1763         // copy the next paragraph to this one
1764         LyXParagraph * the_next = next();
1765    
1766         // first the DTP-stuff
1767 #ifndef NEW_INSETS
1768         LyXParagraph * firstpar = FirstPhysicalPar();
1769         firstpar->params.lineBottom(the_next->params.lineBottom());
1770         firstpar->params.spaceBottom(the_next->params.spaceBottom());
1771         firstpar->params.pagebreakBottom(the_next->params.pagebreakBottom());
1772
1773         size_type pos_end = the_next->text.size() - 1;
1774         size_type pos_insert = Last();
1775 #else
1776         params.lineBottom(the_next->params.lineBottom());
1777         params.spaceBottom(the_next->params.spaceBottom());
1778         params.pagebreakBottom(the_next->params.pagebreakBottom());
1779
1780         size_type pos_end = the_next->text.size() - 1;
1781         size_type pos_insert = size();
1782 #endif
1783
1784         // ok, now copy the paragraph
1785         size_type i, j;
1786         for (i = j = 0; i <= pos_end; ++i) {
1787                 the_next->CutIntoMinibuffer(bparams, i);
1788                 if (InsertFromMinibuffer(pos_insert + j))
1789                         ++j;
1790         }
1791    
1792         // delete the next paragraph
1793         LyXParagraph * ppar = the_next->previous_;
1794         LyXParagraph * npar = the_next->next_;
1795         delete the_next;
1796         ppar->next(npar);
1797 }
1798
1799
1800 #ifndef NEW_INSETS
1801 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1802 {
1803         LyXParagraph * par = ParFromPos(pos);
1804         par = par->next_;
1805         while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1806                 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1807                 par = par->next_;
1808         }
1809 }
1810
1811
1812 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1813 {
1814         LyXParagraph * par = ParFromPos(pos);
1815         par = par->next_;
1816         while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1817                 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1818                 par = par->next_;
1819         }
1820 }
1821 #endif
1822
1823
1824 int LyXParagraph::GetEndLabel(BufferParams const & bparams) const
1825 {
1826         LyXParagraph const * par = this;
1827         int par_depth = GetDepth();
1828         while (par) {
1829                 LyXTextClass::LayoutList::size_type layout = par->GetLayout();
1830                 int const endlabeltype =
1831                         textclasslist.Style(bparams.textclass,
1832                                             layout).endlabeltype;
1833                 if (endlabeltype != END_LABEL_NO_LABEL) {
1834                         LyXParagraph const * last = this;
1835 #ifndef NEW_INSETS
1836                         if (footnoteflag == NO_FOOTNOTE)
1837                                 last = LastPhysicalPar();
1838                         else if (next_->footnoteflag == NO_FOOTNOTE)
1839                                 return endlabeltype;
1840 #else
1841                         last = this;
1842 #endif
1843
1844                         if (!last || !last->next_)
1845                                 return endlabeltype;
1846
1847                         int next_depth = last->next_->GetDepth();
1848                         if (par_depth > next_depth ||
1849                             (par_depth == next_depth && layout != last->next_->GetLayout() ))
1850                                 return endlabeltype;
1851                         break;
1852                 }
1853                 if (par_depth == 0)
1854                         break;
1855                 par = par->DepthHook(par_depth - 1);
1856                 if (par)
1857                         par_depth = par->GetDepth();
1858         }
1859         return END_LABEL_NO_LABEL;
1860 }
1861
1862
1863 LyXTextClass::size_type LyXParagraph::GetLayout() const
1864 {
1865 #ifndef NEW_INSETS
1866         return FirstPhysicalPar()->layout;
1867 #else
1868         return layout;
1869 #endif
1870 }
1871
1872
1873 char LyXParagraph::GetDepth() const
1874 {
1875 #ifndef NEW_INSETS
1876         return FirstPhysicalPar()->params.depth();
1877 #else
1878         return params.depth();
1879 #endif
1880 }
1881
1882
1883 char LyXParagraph::GetAlign() const
1884 {
1885 #ifndef NEW_INSETS
1886         return FirstPhysicalPar()->params.align();
1887 #else
1888         return params.align();
1889 #endif
1890 }
1891
1892
1893 string const & LyXParagraph::GetLabelstring() const
1894 {
1895 #ifndef NEW_INSETS
1896         return FirstPhysicalPar()->params.labelString();
1897 #else
1898         return params.labelString();
1899 #endif
1900 }
1901
1902
1903 int LyXParagraph::GetFirstCounter(int i) const
1904 {
1905 #ifndef NEW_INSETS
1906         return FirstPhysicalPar()->counter_[i];
1907 #else
1908         return counter_[i];
1909 #endif
1910 }
1911
1912
1913 // the next two functions are for the manual labels
1914 string const LyXParagraph::GetLabelWidthString() const
1915 {
1916 #ifndef NEW_INSETS
1917         if (!FirstPhysicalPar()->params.labelWidthString().empty())
1918                 return FirstPhysicalPar()->params.labelWidthString();
1919 #else
1920         if (!params.labelWidthString().empty())
1921                 return params.labelWidthString();
1922 #endif
1923         else
1924                 return _("Senseless with this layout!");
1925 }
1926
1927
1928 void LyXParagraph::SetLabelWidthString(string const & s)
1929 {
1930 #ifndef NEW_INSETS
1931         LyXParagraph * par = FirstPhysicalPar();
1932
1933         par->params.labelWidthString(s);
1934 #else
1935         params.labelWidthString(s);
1936 #endif
1937 }
1938
1939
1940 void LyXParagraph::SetOnlyLayout(BufferParams const & bparams,
1941                                  LyXTextClass::size_type new_layout)
1942 {
1943 #ifndef NEW_INSETS
1944         LyXParagraph * par = FirstPhysicalPar();
1945 #else
1946         LyXParagraph * par = this;
1947 #endif
1948         LyXParagraph * ppar = 0;
1949         LyXParagraph * npar = 0;
1950
1951         par->layout = new_layout;
1952
1953 #ifndef NO_PEXTRA
1954         if (par->params.pextraType() == PEXTRA_NONE) {
1955 #endif
1956                 if (par->previous()) {
1957 #ifndef NEW_INSETS
1958                         ppar = par->previous()->FirstPhysicalPar();
1959 #else
1960                         ppar = par->previous();
1961 #endif
1962                         while(ppar
1963                               && ppar->previous()
1964                               && (ppar->params.depth() > par->params.depth()))
1965 #ifndef NEW_INSETS
1966                                 ppar = ppar->previous()->FirstPhysicalPar();
1967 #else
1968                         ppar = ppar->previous();
1969 #endif
1970                 }
1971                 if (par->next()) {
1972 #ifndef NEW_INSETS
1973                         npar = par->next()->NextAfterFootnote();
1974 #else
1975                         npar = par->next();
1976 #endif
1977                         while(npar
1978                               && npar->next()
1979                               && (npar->params.depth() > par->params.depth()))
1980 #ifndef NEW_INSETS
1981                                 npar = npar->next()->NextAfterFootnote();
1982 #else
1983                         npar = npar->next();
1984 #endif
1985                 }
1986 #ifndef NO_PEXTRA
1987                 if (ppar && (ppar->params.pextraType() != PEXTRA_NONE)) {
1988                         string p1 = ppar->params.pextraWidth();
1989                         string p2 = ppar->params.pextraWidthp();
1990                         ppar->SetPExtraType(bparams,
1991                                             ppar->params.pextraType(),
1992                                             p1, p2);
1993                 }
1994                 if ((par->params.pextraType() == PEXTRA_NONE) &&
1995                     npar && (npar->params.pextraType() != PEXTRA_NONE)) {
1996                         string const p1 = npar->params.pextraWidth();
1997                         string const p2 = npar->params.pextraWidthp();
1998                         npar->SetPExtraType(bparams, npar->params.pextraType(),
1999                                             p1, p2);
2000                 }
2001         }
2002 #endif
2003 }
2004
2005
2006 void LyXParagraph::SetLayout(BufferParams const & bparams,
2007                              LyXTextClass::size_type new_layout)
2008 {
2009         LyXParagraph
2010 #ifndef NEW_INSETS
2011                 * par = FirstPhysicalPar(),
2012 #else
2013                 * par = this,
2014 #endif
2015                 * ppar = 0,
2016                 * npar = 0;
2017
2018         par->layout = new_layout;
2019         par->params.labelWidthString(string());
2020         par->params.align(LYX_ALIGN_LAYOUT);
2021         par->params.spaceTop(VSpace(VSpace::NONE));
2022         par->params.spaceBottom(VSpace(VSpace::NONE));
2023         par->params.spacing(Spacing(Spacing::Default));
2024
2025 #ifndef NO_PEXTRA
2026         if (par->params.pextraType() == PEXTRA_NONE) {
2027 #endif
2028                 if (par->previous()) {
2029 #ifndef NEW_INSETS
2030                         ppar = par->previous()->FirstPhysicalPar();
2031 #else
2032                         ppar = par->previous();
2033 #endif
2034                         while(ppar
2035                               && ppar->previous()
2036                               && (ppar->params.depth() > par->params.depth()))
2037 #ifndef NEW_INSETS
2038                                 ppar = ppar->previous()->FirstPhysicalPar();
2039 #else
2040                         ppar = ppar->previous();
2041 #endif
2042                 }
2043                 if (par->next()) {
2044 #ifndef NEW_INSETS
2045                         npar = par->next()->NextAfterFootnote();
2046 #else
2047                         npar = par->next();
2048 #endif
2049                         while(npar
2050                               && npar->next()
2051                               && (npar->params.depth() > par->params.depth()))
2052 #ifndef NEW_INSETS
2053                                 npar = npar->next()->NextAfterFootnote();
2054 #else
2055                         npar = npar->next();
2056 #endif
2057                 }
2058 #ifndef NO_PEXTRA
2059                 if (ppar && (ppar->params.pextraType() != PEXTRA_NONE)) {
2060                         string const p1 = ppar->params.pextraWidth();
2061                         string const p2 = ppar->params.pextraWidthp();
2062                         ppar->SetPExtraType(bparams, ppar->params.pextraType(),
2063                                             p1, p2);
2064                 }
2065                 if ((par->params.pextraType() == PEXTRA_NONE) &&
2066                     npar && (npar->params.pextraType() != PEXTRA_NONE)) {
2067                         string const p1 = npar->params.pextraWidth();
2068                         string const p2 = npar->params.pextraWidthp();
2069                         npar->SetPExtraType(bparams, npar->params.pextraType(),
2070                                             p1, p2);
2071                 }
2072         }
2073 #endif
2074 }
2075
2076
2077 // if the layout of a paragraph contains a manual label, the beginning of the 
2078 // main body is the beginning of the second word. This is what the par-
2079 // function returns. If the layout does not contain a label, the main
2080 // body always starts with position 0. This differentiation is necessary,
2081 // because there cannot be a newline or a blank <= the beginning of the 
2082 // main body in TeX.
2083
2084 int LyXParagraph::BeginningOfMainBody() const
2085 {
2086 #ifndef NEW_INSETS
2087         if (FirstPhysicalPar() != this)
2088                 return -1;
2089 #endif
2090         // Unroll the first two cycles of the loop
2091         // and remember the previous character to
2092         // remove unnecessary GetChar() calls
2093         size_type i = 0;
2094         if (i < size()
2095             && GetChar(i) != LyXParagraph::META_NEWLINE
2096                 ) {
2097                 ++i;
2098                 char previous_char = 0;
2099                 char temp = 0; 
2100                 if (i < size()
2101                     && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2102                         // Yes, this  ^ is supposed to be "= " not "=="
2103                         ++i;
2104                         while (i < size()
2105                                && previous_char != ' '
2106                                && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2107                                 ++i;
2108                                 previous_char = temp;
2109                         }
2110                 }
2111         }
2112
2113 #ifndef NEW_INSETS
2114         if (i == 0 && i == size() &&
2115             !(footnoteflag == LyXParagraph::NO_FOOTNOTE
2116               && next_ && next_->footnoteflag != LyXParagraph::NO_FOOTNOTE))
2117                 ++i;                           /* the cursor should not jump  
2118                                                 * to the main body if there
2119                                                 * is nothing in! */
2120 #endif
2121         return i;
2122 }
2123
2124
2125 LyXParagraph * LyXParagraph::DepthHook(int deth)
2126 {
2127         LyXParagraph * newpar = this;
2128         if (deth < 0)
2129                 return 0;
2130    
2131         do {
2132 #ifndef NEW_INSETS
2133                 newpar = newpar->FirstPhysicalPar()->previous();
2134 #else
2135                 newpar = newpar->previous();
2136 #endif
2137         } while (newpar && newpar->GetDepth() > deth
2138 #ifndef NEW_INSETS
2139                  && newpar->footnoteflag == footnoteflag
2140 #endif
2141                 );
2142    
2143         if (!newpar) {
2144                 if (previous() || GetDepth())
2145                         lyxerr << "ERROR (LyXParagraph::DepthHook): "
2146                                 "no hook." << endl;
2147                 newpar = this;
2148         }
2149 #ifndef NEW_INSETS
2150         return newpar->FirstPhysicalPar();
2151 #else
2152         return newpar;
2153 #endif
2154 }
2155
2156
2157 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
2158 {
2159         LyXParagraph const * newpar = this;
2160         if (deth < 0)
2161                 return 0;
2162    
2163         do {
2164 #ifndef NEW_INSETS
2165                 newpar = newpar->FirstPhysicalPar()->previous();
2166 #else
2167                 newpar = newpar->previous();
2168 #endif
2169         } while (newpar && newpar->GetDepth() > deth
2170 #ifndef NEW_INSETS
2171                  && newpar->footnoteflag == footnoteflag
2172 #endif
2173                 );
2174    
2175         if (!newpar) {
2176                 if (previous() || GetDepth())
2177                         lyxerr << "ERROR (LyXParagraph::DepthHook): "
2178                                 "no hook." << endl;
2179                 newpar = this;
2180         }
2181 #ifndef NEW_INSETS
2182         return newpar->FirstPhysicalPar();
2183 #else
2184         return newpar;
2185 #endif
2186 }
2187
2188
2189 int LyXParagraph::AutoDeleteInsets()
2190 {
2191         int count = 0;
2192         InsetList::size_type index = 0;
2193         while (index < insetlist.size()) {
2194                 if (insetlist[index].inset && insetlist[index].inset->AutoDelete()) {
2195                         Erase(insetlist[index].pos); 
2196                         // Erase() calls to insetlist.erase(&insetlist[index])
2197                         // so index shouldn't be increased.
2198                         ++count;
2199                 } else
2200                         ++index;
2201         }
2202         return count;
2203 }
2204
2205
2206 LyXParagraph::inset_iterator
2207 LyXParagraph::InsetIterator(LyXParagraph::size_type pos)
2208 {
2209         InsetTable search_inset(pos, 0);
2210         InsetList::iterator it = lower_bound(insetlist.begin(),
2211                                              insetlist.end(),
2212                                              search_inset, matchIT());
2213         return inset_iterator(it);
2214 }
2215
2216
2217 // returns -1 if inset not found
2218 int LyXParagraph::GetPositionOfInset(Inset * inset) const
2219 {
2220         // Find the entry.
2221         for (InsetList::const_iterator cit = insetlist.begin();
2222              cit != insetlist.end(); ++cit) {
2223                 if ((*cit).inset == inset) {
2224                         return (*cit).pos;
2225                 }
2226         }
2227         if (inset == bibkey)
2228                 return 0;
2229
2230 #ifndef NEW_INSETS
2231         // Think about footnotes.
2232         if (footnoteflag == LyXParagraph::NO_FOOTNOTE 
2233             && next_ && next_->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2234                 int const further = 
2235                         NextAfterFootnote()->GetPositionOfInset(inset);
2236                 if (further != -1)
2237                         return text.size() + 1 + further;
2238         }
2239 #endif
2240         return -1;
2241 }
2242
2243
2244 LyXParagraph * LyXParagraph::TeXOnePar(Buffer const * buf,
2245                                        BufferParams const & bparams,
2246                                        ostream & os, TexRow & texrow,
2247                                        bool moving_arg
2248 #ifndef NEW_INSETS
2249                                        , 
2250                                        ostream & foot,
2251                                        TexRow & foot_texrow,
2252                                        int & foot_count
2253 #endif
2254         )
2255 {
2256         lyxerr[Debug::LATEX] << "TeXOnePar...     " << this << endl;
2257         LyXLayout const & style =
2258                 textclasslist.Style(bparams.textclass,
2259                                     layout);
2260
2261         bool further_blank_line = false;
2262 #ifndef NEW_INSETS
2263         if (IsDummy())
2264                 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2265 #endif
2266
2267         if (params.startOfAppendix()) {
2268                 os << "\\appendix\n";
2269                 texrow.newline();
2270         }
2271
2272         if (!params.spacing().isDefault()
2273             && (!previous() || !previous()->HasSameLayout(this))) {
2274                 os << params.spacing().writeEnvirBegin() << "\n";
2275                 texrow.newline();
2276         }
2277         
2278         if (tex_code_break_column && style.isCommand()){
2279                 os << '\n';
2280                 texrow.newline();
2281         }
2282
2283         if (params.pagebreakTop()) {
2284                 os << "\\newpage";
2285                 further_blank_line = true;
2286         }
2287         if (params.spaceTop().kind() != VSpace::NONE) {
2288                 os << params.spaceTop().asLatexCommand(bparams);
2289                 further_blank_line = true;
2290         }
2291       
2292         if (params.lineTop()) {
2293                 os << "\\lyxline{\\" << getFont(bparams, 0).latexSize() << '}'
2294                    << "\\vspace{-1\\parskip}";
2295                 further_blank_line = true;
2296         }
2297
2298         if (further_blank_line){
2299                 os << '\n';
2300                 texrow.newline();
2301         }
2302
2303         Language const * language = getParLanguage(bparams);
2304         Language const * doc_language = bparams.language;
2305         Language const * previous_language = previous_
2306                 ? previous_->getParLanguage(bparams) : doc_language;
2307         if (language->babel() != doc_language->babel() &&
2308             language->babel() != previous_language->babel()) {
2309                 os << subst(lyxrc.language_command_begin, "$$lang",
2310                             language->babel())
2311                    << endl;
2312                 texrow.newline();
2313         }
2314
2315         if (bparams.inputenc == "auto" &&
2316             language->encoding() != previous_language->encoding()) {
2317                 os << "\\inputencoding{"
2318                    << language->encoding()->LatexName()
2319                    << "}" << endl;
2320                 texrow.newline();
2321         }
2322         
2323         switch (style.latextype) {
2324         case LATEX_COMMAND:
2325                 os << '\\'
2326                    << style.latexname()
2327                    << style.latexparam();
2328                 break;
2329         case LATEX_ITEM_ENVIRONMENT:
2330                 if (bibkey) {
2331                         bibkey->Latex(buf, os, false, false);
2332                 } else
2333                         os << "\\item ";
2334                 break;
2335         case LATEX_LIST_ENVIRONMENT:
2336                 os << "\\item ";
2337                 break;
2338         default:
2339                 break;
2340         }
2341
2342         bool need_par = SimpleTeXOnePar(buf, bparams, os, texrow, moving_arg);
2343  
2344         LyXParagraph * par = next_;
2345 #ifndef NEW_INSETS
2346         // Spit out footnotes
2347         if (lyxrc.rtl_support) {
2348                 if (next_ && next_->footnoteflag != LyXParagraph::NO_FOOTNOTE
2349                     && next_->footnoteflag != footnoteflag) {
2350                         LyXParagraph * p = 0;
2351                         bool is_rtl = (size() > 0) 
2352                                 ? GetFontSettings(bparams,
2353                                                   size()-1).isRightToLeft()
2354                                 : language->RightToLeft();
2355                         if ((p = NextAfterFootnote()) != 0 &&
2356                              p->size() > 0 &&
2357                              p->GetFontSettings(bparams, 0).isRightToLeft() != is_rtl)
2358                                 is_rtl = getParLanguage(bparams)->RightToLeft();
2359                         while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2360                                && par->footnoteflag != footnoteflag) {
2361                                 par = par->TeXFootnote(buf, bparams,
2362                                                        os, texrow, foot,
2363                                                        foot_texrow, foot_count,
2364                                                        is_rtl);
2365                                 par->SimpleTeXOnePar(buf, bparams,
2366                                                      os, texrow, moving_arg);
2367                                 is_rtl = (par->size() > 0)
2368                                         ? par->GetFontSettings(bparams,
2369                                                                par->size()-1).isRightToLeft()
2370                                         : language->RightToLeft();
2371                                 if (par->next_ &&
2372                                     par->next_->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2373                                     (p = par->NextAfterFootnote()) != 0 &&
2374                                     p->size() > 0 &&
2375                                     p->GetFontSettings(bparams, 0).isRightToLeft() != is_rtl)
2376                                         is_rtl = language->RightToLeft();
2377                                 par = par->next_;
2378                         }
2379                 }
2380         } else {
2381                 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2382                        && par->footnoteflag != footnoteflag) {
2383                         par = par->TeXFootnote(buf, bparams,
2384                                                os, texrow,
2385                                                foot, foot_texrow, foot_count,
2386                                                false);
2387                         par->SimpleTeXOnePar(buf, bparams, os, texrow, moving_arg);
2388                         par = par->next_;
2389                 }
2390         }
2391 #endif
2392
2393         // Make sure that \\par is done with the font of the last
2394         // character if this has another size as the default.
2395         // This is necessary because LaTeX (and LyX on the screen)
2396         // calculates the space between the baselines according
2397         // to this font. (Matthias)
2398         //
2399         // Is this really needed ? (Dekel)
2400         // We do not need to use to change the font for the last paragraph
2401         // or for a command.
2402 #ifndef NEW_INSETS
2403         LyXFont font = getFont(bparams, Last() - 1);
2404 #else
2405         LyXFont font = getFont(bparams, size() - 1);
2406 #endif
2407         bool is_command = textclasslist.Style(bparams.textclass,
2408                                               GetLayout()).isCommand();
2409         if (style.resfont.size() != font.size() && next_ && !is_command) {
2410                 if (!need_par)
2411                         os << "{";
2412                 os << "\\" << font.latexSize() << " \\par}";
2413         } else if (need_par) {
2414                 os << "\\par}";
2415         } else if (is_command)
2416                 os << "}";
2417
2418         if (language->babel() != doc_language->babel() &&
2419             (!par
2420 #ifndef NEW_INSETS
2421              || (footnoteflag != NO_FOOTNOTE && par->footnoteflag != footnoteflag)
2422 #endif
2423              || par->getParLanguage(bparams)->babel() != language->babel())) {
2424                 os << endl 
2425                    << subst(lyxrc.language_command_end, "$$lang",
2426                             doc_language->babel());
2427         }
2428         
2429         switch (style.latextype) {
2430         case LATEX_ITEM_ENVIRONMENT:
2431         case LATEX_LIST_ENVIRONMENT:
2432                 if (par && (params.depth() < par->params.depth())) {
2433                         os << '\n';
2434                         texrow.newline();
2435                 }
2436                 break;
2437         case LATEX_ENVIRONMENT:
2438                 // if its the last paragraph of the current environment
2439                 // skip it otherwise fall through
2440                 if (par
2441                     && (par->layout != layout
2442                         || par->params.depth() != params.depth()
2443 #ifndef NO_PEXTRA
2444                         || par->params.pextraType() != params.pextraType()
2445 #endif
2446                             ))
2447                         break;
2448         default:
2449                 // we don't need it for the last paragraph!!!
2450                 // or for tables in floats
2451                 //   -- effectively creates a \par where there isn't one which
2452                 //      breaks a \subfigure or \subtable.
2453                 if (next_) {
2454 //                  && footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2455                         os << '\n';
2456                         texrow.newline();
2457                 }
2458         }
2459         
2460         further_blank_line = false;
2461         if (params.lineBottom()) {
2462 #ifndef NEW_INSETS
2463                 os << "\\lyxline{\\" << getFont(bparams,
2464                                                 Last() - 1).latexSize() << '}';
2465 #else
2466                 os << "\\lyxline{\\" << getFont(bparams,
2467                                                 size() - 1).latexSize() << '}';
2468 #endif
2469                 further_blank_line = true;
2470         }
2471
2472         if (params.spaceBottom().kind() != VSpace::NONE) {
2473                 os << params.spaceBottom().asLatexCommand(bparams);
2474                 further_blank_line = true;
2475         }
2476       
2477         if (params.pagebreakBottom()) {
2478                 os << "\\newpage";
2479                 further_blank_line = true;
2480         }
2481
2482         if (further_blank_line){
2483                 os << '\n';
2484                 texrow.newline();
2485         }
2486
2487         if (!params.spacing().isDefault()
2488             && (!par || !par->HasSameLayout(this))) {
2489                 os << params.spacing().writeEnvirEnd() << "\n";
2490                 texrow.newline();
2491         }
2492         
2493         // we don't need it for the last paragraph!!!
2494         if (next_
2495 #ifndef NEW_INSETS
2496             && !(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2497               par->footnoteflag == LyXParagraph::NO_FOOTNOTE)
2498 #endif
2499                 ) {
2500                 os << '\n';
2501                 texrow.newline();
2502         }
2503
2504         lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2505         return par;
2506 }
2507
2508
2509 // This one spits out the text of the paragraph
2510 bool LyXParagraph::SimpleTeXOnePar(Buffer const * buf,
2511                                    BufferParams const & bparams,
2512                                    ostream & os, TexRow & texrow,
2513                                    bool moving_arg)
2514 {
2515         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...     " << this << endl;
2516
2517         bool return_value = false;
2518
2519         LyXLayout const & style =
2520                 textclasslist.Style(bparams.textclass,
2521                                     GetLayout());
2522         LyXFont basefont, last_font;
2523
2524         // Maybe we have to create a optional argument.
2525         size_type main_body;
2526         if (style.labeltype != LABEL_MANUAL)
2527                 main_body = 0;
2528         else
2529                 main_body = BeginningOfMainBody();
2530
2531         if (main_body > 0) {
2532                 os << '[';
2533                 basefont = getFont(bparams, -2); // Get label font
2534         } else {
2535                 basefont = getFont(bparams, -1); // Get layout font
2536         }
2537
2538         int column = 0;
2539
2540         if (main_body >= 0
2541             && !text.size()
2542 #ifndef NEW_INSETS
2543             && !IsDummy()
2544 #endif
2545                 ) {
2546                 if (style.isCommand()) {
2547                         os << '{';
2548                         ++column;
2549                 } else if (params.align() != LYX_ALIGN_LAYOUT) {
2550                         os << '{';
2551                         ++column;
2552                         return_value = true;
2553                 }
2554         }
2555
2556         moving_arg |= style.needprotect;
2557  
2558         // Which font is currently active?
2559         LyXFont running_font(basefont);
2560         // Do we have an open font change?
2561         bool open_font = false;
2562
2563         texrow.start(this, 0);
2564
2565         for (size_type i = 0; i < size(); ++i) {
2566                 ++column;
2567                 // First char in paragraph or after label?
2568                 if (i == main_body
2569 #ifndef NEW_INSETS
2570                     && !IsDummy()
2571 #endif
2572                         ) {
2573                         if (main_body > 0) {
2574                                 if (open_font) {
2575                                         column += running_font.latexWriteEndChanges(os, basefont, basefont);
2576                                         open_font = false;
2577                                 }
2578                                 basefont = getFont(bparams, -1); // Now use the layout font
2579                                 running_font = basefont;
2580                                 os << ']';
2581                                 ++column;
2582                         }
2583                         if (style.isCommand()) {
2584                                 os << '{';
2585                                 ++column;
2586                         } else if (params.align() != LYX_ALIGN_LAYOUT && next_) {
2587                                 // We do not need \par here (Dekel)
2588                                 // os << "{\\par";
2589                                 os << "{";
2590                                 ++column;
2591                                 return_value = true;
2592                         }
2593
2594                         if (params.noindent()) {
2595                                 os << "\\noindent ";
2596                                 column += 10;
2597                         }
2598                         switch (params.align()) {
2599                         case LYX_ALIGN_NONE:
2600                         case LYX_ALIGN_BLOCK:
2601                         case LYX_ALIGN_LAYOUT:
2602                         case LYX_ALIGN_SPECIAL:
2603                                 break;
2604                         case LYX_ALIGN_LEFT:
2605                                 if (moving_arg)
2606                                         os << "\\protect";
2607                                 if (getParLanguage(bparams)->babel() != "hebrew") {
2608                                         os << "\\raggedright ";
2609                                         column+= 13;
2610                                 } else {
2611                                         os << "\\raggedleft ";
2612                                         column+= 12;
2613                                 }
2614                                 break;
2615                         case LYX_ALIGN_RIGHT:
2616                                 if (moving_arg)
2617                                         os << "\\protect";
2618                                 if (getParLanguage(bparams)->babel() != "hebrew") {
2619                                         os << "\\raggedleft ";
2620                                         column+= 12;
2621                                 } else {
2622                                         os << "\\raggedright ";
2623                                         column+= 13;
2624                                 }
2625                                 break;
2626                         case LYX_ALIGN_CENTER:
2627                                 if (moving_arg)
2628                                         os << "\\protect";
2629                                 os << "\\centering ";
2630                                 column+= 11;
2631                                 break;
2632                         }        
2633                 }
2634
2635                 value_type c = GetChar(i);
2636
2637                 // Fully instantiated font
2638                 LyXFont font = getFont(bparams, i);
2639 #ifndef NEW_INSETS
2640                 LyXParagraph * p = 0;
2641                 if (i == 0
2642                     && previous_ && 
2643                     previous_->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2644                     (p = PreviousBeforeFootnote()) != 0)
2645                         last_font = p->getFont(bparams, p->size() - 1);
2646                 else
2647 #endif
2648                         last_font = running_font;
2649
2650                 // Spaces at end of font change are simulated to be
2651                 // outside font change, i.e. we write "\textXX{text} "
2652                 // rather than "\textXX{text }". (Asger)
2653                 if (open_font && c == ' ' && i <= size() - 2 
2654                     && !getFont(bparams, i + 1).equalExceptLatex(running_font) 
2655                     && !getFont(bparams, i + 1).equalExceptLatex(font)) {
2656                         font = getFont(bparams, i + 1);
2657                 }
2658                 // We end font definition before blanks
2659                 if (!font.equalExceptLatex(running_font) && open_font) {
2660                         column += running_font.latexWriteEndChanges(os,
2661                                                                     basefont,
2662                                                                     (i == main_body-1) ? basefont : font);
2663                         running_font = basefont;
2664                         open_font = false;
2665                 }
2666
2667                 // Blanks are printed before start of fontswitch
2668                 if (c == ' ') {
2669                         // Do not print the separation of the optional argument
2670                         if (i != main_body - 1) {
2671                                 SimpleTeXBlanks(os, texrow, i,
2672                                                 column, font, style);
2673                         }
2674                 }
2675
2676                 // Do we need to change font?
2677                 if (!font.equalExceptLatex(running_font)
2678                     && i != main_body-1) {
2679                         column += font.latexWriteStartChanges(os, basefont,
2680                                                               last_font);
2681                         running_font = font;
2682                         open_font = true;
2683                 }
2684
2685                 if (c == LyXParagraph::META_NEWLINE) {
2686                         // newlines are handled differently here than
2687                         // the default in SimpleTeXSpecialChars().
2688                         if (!style.newline_allowed
2689                             || font.latex() == LyXFont::ON) {
2690                                 os << '\n';
2691                         } else {
2692                                 if (open_font) {
2693                                         column += running_font.latexWriteEndChanges(os, basefont, basefont);
2694                                         open_font = false;
2695                                 }
2696                                 basefont = getFont(bparams, -1);
2697                                 running_font = basefont;
2698                                 if (font.family() == 
2699                                     LyXFont::TYPEWRITER_FAMILY) {
2700                                         os << "~";
2701                                 }
2702                                 if (moving_arg)
2703                                         os << "\\protect ";
2704                                 os << "\\\\\n";
2705                         }
2706                         texrow.newline();
2707                         texrow.start(this, i + 1);
2708                         column = 0;
2709                 } else {
2710                         SimpleTeXSpecialChars(buf, bparams,
2711                                               os, texrow, moving_arg,
2712                                               font, running_font, basefont,
2713                                               open_font, style, i, column, c);
2714                 }
2715         }
2716
2717         // If we have an open font definition, we have to close it
2718         if (open_font) {
2719                 LyXParagraph * p = 0;
2720                 if (next_
2721 #ifndef NEW_INSETS
2722                     && next_->footnoteflag != LyXParagraph::NO_FOOTNOTE
2723                     && (p =  NextAfterFootnote()) != 0
2724 #else
2725                         && (p = next_)
2726 #endif
2727                 )
2728                         running_font.latexWriteEndChanges(os, basefont,
2729                                                           p->getFont(bparams, 0));
2730                 else
2731                         running_font.latexWriteEndChanges(os, basefont, basefont);
2732         }
2733
2734         // Needed if there is an optional argument but no contents.
2735         if (main_body > 0 && main_body == size()) {
2736                 os << "]~";
2737                 return_value = false;
2738         }
2739
2740         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2741         return return_value;
2742 }
2743
2744
2745 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2746 {
2747         bool retval = false;
2748         switch (c) {
2749         case LyXParagraph::META_HFILL:
2750                 sgml_string.erase();
2751                 break;
2752         case LyXParagraph::META_NEWLINE:
2753                 sgml_string = '\n';
2754                 break;
2755         case '&': 
2756                 sgml_string = "&amp;";
2757                 break;
2758         case '<': 
2759                 sgml_string = "&lt;"; 
2760                 break;
2761         case '>':
2762                 sgml_string = "&gt;"; 
2763                 break;
2764         case '$': 
2765                 sgml_string = "&dollar;"; 
2766                 break;
2767         case '#': 
2768                 sgml_string = "&num;";
2769                 break;
2770         case '%': 
2771                 sgml_string = "&percnt;";
2772                 break;
2773         case '[': 
2774                 sgml_string = "&lsqb;";
2775                 break;
2776         case ']': 
2777                 sgml_string = "&rsqb;";
2778                 break;
2779         case '{': 
2780                 sgml_string = "&lcub;";
2781                 break;
2782         case '}': 
2783                 sgml_string = "&rcub;";
2784                 break;
2785         case '~': 
2786                 sgml_string = "&tilde;";
2787                 break;
2788         case '"': 
2789                 sgml_string = "&quot;";
2790                 break;
2791         case '\\': 
2792                 sgml_string = "&bsol;";
2793                 break;
2794         case ' ':
2795                 retval = true;
2796                 sgml_string = ' ';
2797                 break;
2798         case '\0': // Ignore :-)
2799                 sgml_string.erase();
2800                 break;
2801         default:
2802                 sgml_string = c;
2803                 break;
2804         }
2805         return retval;
2806 }
2807
2808
2809 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
2810                                    LyXParagraph::size_type const i,
2811                                    int & column, LyXFont const & font,
2812                                    LyXLayout const & style)
2813 {
2814         if (column > tex_code_break_column
2815             && i 
2816             && GetChar(i - 1) != ' '
2817             && (i < size() - 1)
2818             // In LaTeX mode, we don't want to
2819             // break lines since some commands
2820             // do not like this
2821             && ! (font.latex() == LyXFont::ON)
2822             // same in FreeSpacing mode
2823             && !style.free_spacing
2824             // In typewriter mode, we want to avoid 
2825             // ! . ? : at the end of a line
2826             && !(font.family() == LyXFont::TYPEWRITER_FAMILY
2827                  && (GetChar(i-1) == '.'
2828                      || GetChar(i-1) == '?' 
2829                      || GetChar(i-1) == ':'
2830                      || GetChar(i-1) == '!'))) {
2831                 if (tex_code_break_column == 0) {
2832                         // in batchmode we need LaTeX to still
2833                         // see it as a space not as an extra '\n'
2834                         os << " %\n";
2835                 } else {
2836                         os << '\n';
2837                 }
2838                 texrow.newline();
2839                 texrow.start(this, i + 1);
2840                 column = 0;
2841         } else if (font.latex() == LyXFont::OFF) {
2842                 if (style.free_spacing) {
2843                         os << '~';
2844                 } else {
2845                         os << ' ';
2846                 }
2847         }
2848 }
2849
2850
2851 void LyXParagraph::SimpleTeXSpecialChars(Buffer const * buf,
2852                                          BufferParams const & bparams,
2853                                          ostream & os, TexRow & texrow,
2854                                          bool moving_arg,
2855                                          LyXFont & font,
2856                                          LyXFont & running_font,
2857                                          LyXFont & basefont,
2858                                          bool & open_font,
2859                                          LyXLayout const & style,
2860                                          LyXParagraph::size_type & i,
2861                                          int & column,
2862                                          LyXParagraph::value_type const c)
2863 {
2864         // Two major modes:  LaTeX or plain
2865         // Handle here those cases common to both modes
2866         // and then split to handle the two modes separately.
2867         switch (c) {
2868         case LyXParagraph::META_INSET: {
2869                 Inset * inset = GetInset(i);
2870                 if (inset) {
2871                         bool close = false;
2872                         int const len = os.tellp();
2873                         //ostream::pos_type const len = os.tellp();
2874                         if ((inset->LyxCode() == Inset::GRAPHICS_CODE
2875                              || inset->LyxCode() == Inset::MATH_CODE
2876                              || inset->LyxCode() == Inset::URL_CODE)
2877                             && running_font.isRightToLeft()) {
2878                                 os << "\\L{";
2879                                 close = true;
2880                         }
2881
2882                         int tmp = inset->Latex(buf, os, moving_arg,
2883                                                style.free_spacing);
2884
2885                         if (close)
2886                                 os << "}";
2887
2888                         if (tmp) {
2889                                 column = 0;
2890                         } else {
2891                                 column += int(os.tellp()) - len;
2892                         }
2893                         for (; tmp--;) {
2894                                 texrow.newline();
2895                         }
2896                 }
2897         }
2898         break;
2899
2900         case LyXParagraph::META_NEWLINE:
2901                 if (open_font) {
2902                         column += running_font.latexWriteEndChanges(os,
2903                                                                     basefont,
2904                                                                     basefont);
2905                         open_font = false;
2906                 }
2907                 basefont = getFont(bparams, -1);
2908                 running_font = basefont;
2909                 break;
2910
2911         case LyXParagraph::META_HFILL: 
2912                 os << "\\hfill{}";
2913                 column += 7;
2914                 break;
2915
2916         default:
2917                 // And now for the special cases within each mode
2918                 // Are we in LaTeX mode?
2919                 if (font.latex() == LyXFont::ON) {
2920                         // at present we only have one option
2921                         // but I'll leave it as a switch statement
2922                         // so its simpler to extend. (ARRae)
2923                         switch (c) {
2924                         default:
2925                                 // make sure that we will not print
2926                                 // error generating chars to the tex
2927                                 // file. This test would not be needed
2928                                 // if it were done in the buffer
2929                                 // itself.
2930                                 if (c != '\0') {
2931                                         os << c;
2932                                 }
2933                                 break;
2934                         }
2935                 } else {
2936                         // Plain mode (i.e. not LaTeX)
2937                         switch (c) {
2938                         case '\\': 
2939                                 os << "\\textbackslash{}";
2940                                 column += 15;
2941                                 break;
2942                 
2943                         case '°': case '±': case '²': case '³':  
2944                         case '×': case '÷': case '¹': case 'ª':
2945                         case 'º': case '¬': case 'µ':
2946                                 if (bparams.inputenc == "latin1" ||
2947                                     (bparams.inputenc == "auto" &&
2948                                      font.language()->encoding()->LatexName()
2949                                      == "latin1")) {
2950                                         os << "\\ensuremath{"
2951                                            << c
2952                                            << '}';
2953                                         column += 13;
2954                                 } else {
2955                                         os << c;
2956                                 }
2957                                 break;
2958
2959                         case '|': case '<': case '>':
2960                                 // In T1 encoding, these characters exist
2961                                 if (lyxrc.fontenc == "T1") {
2962                                         os << c;
2963                                         //... but we should avoid ligatures
2964                                         if ((c == '>' || c == '<')
2965                                             && i <= size() - 2
2966                                             && GetChar(i + 1) == c) {
2967                                                 //os << "\\textcompwordmark{}";
2968                                                 // Jean-Marc, have a look at
2969                                                 // this. I think this works
2970                                                 // equally well:
2971                                                 os << "\\,{}";
2972                                                 // Lgb
2973                                                 column += 19;
2974                                         }
2975                                         break;
2976                                 }
2977                                 // Typewriter font also has them
2978                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
2979                                         os << c;
2980                                         break;
2981                                 } 
2982                                 // Otherwise, we use what LaTeX
2983                                 // provides us.
2984                                 switch (c) {
2985                                 case '<':
2986                                         os << "\\textless{}";
2987                                         column += 10;
2988                                         break;
2989                                 case '>':
2990                                         os << "\\textgreater{}";
2991                                         column += 13;
2992                                         break;
2993                                 case '|':
2994                                         os << "\\textbar{}";
2995                                         column += 9;
2996                                         break;
2997                                 }
2998                                 break;
2999
3000                         case '-': // "--" in Typewriter mode -> "-{}-"
3001                                 if (i <= size() - 2
3002                                     && GetChar(i + 1) == '-'
3003                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3004                                         os << "-{}";
3005                                         column += 2;
3006                                 } else {
3007                                         os << '-';
3008                                 }
3009                                 break;
3010
3011                         case '\"': 
3012                                 os << "\\char`\\\"{}";
3013                                 column += 9;
3014                                 break;
3015
3016                         case '£':
3017                                 if (bparams.inputenc == "default") {
3018                                         os << "\\pounds{}";
3019                                         column += 8;
3020                                 } else {
3021                                         os << c;
3022                                 }
3023                                 break;
3024
3025                         case '$': case '&':
3026                         case '%': case '#': case '{':
3027                         case '}': case '_':
3028                                 os << '\\' << c;
3029                                 column += 1;
3030                                 break;
3031
3032                         case '~':
3033                                 os << "\\textasciitilde{}";
3034                                 column += 16;
3035                                 break;
3036
3037                         case '^':
3038                                 os << "\\textasciicircum{}";
3039                                 column += 17;
3040                                 break;
3041
3042                         case '*': case '[': case ']':
3043                                 // avoid being mistaken for optional arguments
3044                                 os << '{' << c << '}';
3045                                 column += 2;
3046                                 break;
3047
3048                         case ' ':
3049                                 // Blanks are printed before font switching.
3050                                 // Sure? I am not! (try nice-latex)
3051                                 // I am sure it's correct. LyX might be smarter
3052                                 // in the future, but for now, nothing wrong is
3053                                 // written. (Asger)
3054                                 break;
3055
3056                         default:
3057                                 /* idea for labels --- begin*/
3058                                 // Check for "LyX"
3059                                 if (c ==  'L'
3060                                     && i <= size() - 3
3061                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
3062                                     && GetChar(i + 1) == 'y'
3063                                     && GetChar(i + 2) == 'X') {
3064                                         os << "\\LyX{}";
3065                                         i += 2;
3066                                         column += 5;
3067                                 }
3068                                 // Check for "TeX"
3069                                 else if (c == 'T'
3070                                          && i <= size() - 3
3071                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3072                                          && GetChar(i + 1) == 'e'
3073                                          && GetChar(i + 2) == 'X') {
3074                                         os << "\\TeX{}";
3075                                         i += 2;
3076                                         column += 5;
3077                                 }
3078                                 // Check for "LaTeX2e"
3079                                 else if (c == 'L'
3080                                          && i <= size() - 7
3081                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3082                                          && GetChar(i + 1) == 'a'
3083                                          && GetChar(i + 2) == 'T'
3084                                          && GetChar(i + 3) == 'e'
3085                                          && GetChar(i + 4) == 'X'
3086                                          && GetChar(i + 5) == '2'
3087                                          && GetChar(i + 6) == 'e') {
3088                                         os << "\\LaTeXe{}";
3089                                         i += 6;
3090                                         column += 8;
3091                                 }
3092                                 // Check for "LaTeX"
3093                                 else if (c == 'L'
3094                                          && i <= size() - 5
3095                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3096                                          && GetChar(i + 1) == 'a'
3097                                          && GetChar(i + 2) == 'T'
3098                                          && GetChar(i + 3) == 'e'
3099                                          && GetChar(i + 4) == 'X') {
3100                                         os << "\\LaTeX{}";
3101                                         i += 4;
3102                                         column += 7;
3103                                         /* idea for labels --- end*/ 
3104                                 } else if (c != '\0') {
3105                                         os << c;
3106                                 }
3107                                 break;
3108                         }
3109                 }
3110         }
3111 }
3112
3113
3114 LyXParagraph * LyXParagraph::TeXDeeper(Buffer const * buf,
3115                                        BufferParams const & bparams,
3116                                        ostream & os, TexRow & texrow
3117 #ifndef NEW_INSETS
3118                                        ,ostream & foot,
3119                                        TexRow & foot_texrow,
3120                                        int & foot_count
3121 #endif
3122         )
3123 {
3124         lyxerr[Debug::LATEX] << "TeXDeeper...     " << this << endl;
3125         LyXParagraph * par = this;
3126
3127         while (par &&
3128                (par->params.depth() == params.depth())
3129 #ifndef NEW_INSETS
3130                && (par->footnoteflag == footnoteflag)
3131 #endif
3132                 ) {
3133 #ifndef NEW_INSETS
3134                 if (par->IsDummy())
3135                         lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3136 #endif
3137                 if (textclasslist.Style(bparams.textclass, 
3138                                         par->layout).isEnvironment()
3139 #ifndef NO_PEXTRA
3140                     || par->params.pextraType() != PEXTRA_NONE
3141 #endif
3142                         ) {
3143                         par = par->TeXEnvironment(buf, bparams,
3144                                                   os, texrow
3145 #ifndef NEW_INSETS
3146                                                   ,foot, foot_texrow,
3147                                                   foot_count
3148 #endif
3149                                 );
3150                 } else {
3151                         par = par->TeXOnePar(buf, bparams,
3152                                              os, texrow, false
3153 #ifndef NEW_INSETS
3154                                              ,
3155                                              foot, foot_texrow,
3156                                              foot_count
3157 #endif
3158                                 );
3159                 }
3160         }
3161         lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3162
3163         return par;
3164 }
3165
3166
3167 LyXParagraph * LyXParagraph::TeXEnvironment(Buffer const * buf,
3168                                             BufferParams const & bparams,
3169                                             ostream & os, TexRow & texrow
3170 #ifndef NEW_INSETS
3171                                             ,ostream & foot,
3172                                             TexRow & foot_texrow,
3173                                             int & foot_count
3174 #endif
3175         )
3176 {
3177 #ifndef NO_PEXTRA
3178         bool eindent_open = false;
3179 #endif
3180 #ifndef NEW_INSETS
3181         bool foot_this_level = false;
3182 #endif
3183 #ifndef NO_PEXTRA
3184         // flags when footnotetext should be appended to file.
3185         static bool minipage_open = false;
3186         static int minipage_open_depth = 0;
3187         char par_sep = bparams.paragraph_separation;
3188 #endif
3189     
3190         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << this << endl;
3191 #ifndef NEW_INSETS
3192         if (IsDummy())
3193                 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3194 #endif
3195
3196         LyXLayout const & style =
3197                 textclasslist.Style(bparams.textclass,
3198                                     layout);
3199
3200 #ifndef NO_PEXTRA
3201         if (params.pextraType() == PEXTRA_INDENT) {
3202                 if (!params.pextraWidth().empty()) {
3203                         os << "\\begin{LyXParagraphIndent}{"
3204                            << params.pextraWidth() << "}\n";
3205                 } else {
3206                         //float ib = atof(pextra_widthp.c_str())/100;
3207                         // string can't handle floats at present (971109)
3208                         // so I'll do a conversion by hand knowing that
3209                         // the limits are 0.0 to 1.0. ARRae.
3210                         os << "\\begin{LyXParagraphIndent}{";
3211                         switch (params.pextraWidthp().length()) {
3212                         case 3:
3213                                 os << "1.00";
3214                                 break;
3215                         case 2:
3216                                 os << "0."
3217                                    << params.pextraWidthp();
3218                                 break;
3219                         case 1:
3220                                 os << "0.0"
3221                                    << params.pextraWidthp();
3222                         }
3223                         os << "\\columnwidth}\n";
3224                 }
3225                 texrow.newline();
3226                 eindent_open = true;
3227         }
3228         if ((params.pextraType() == PEXTRA_MINIPAGE) && !minipage_open) {
3229                 if (params.pextraHfill() && previous() &&
3230                     (previous()->params.pextraType() == PEXTRA_MINIPAGE)) {
3231                         os << "\\hfill{}\n";
3232                         texrow.newline();
3233                 }
3234                 if (par_sep == BufferParams::PARSEP_INDENT) {
3235                         os << "{\\setlength\\parindent{0pt}\n";
3236                         texrow.newline();
3237                 }
3238                 os << "\\begin{minipage}";
3239                 switch (params.pextraAlignment()) {
3240                 case MINIPAGE_ALIGN_TOP:
3241                         os << "[t]";
3242                         break;
3243                 case MINIPAGE_ALIGN_MIDDLE:
3244                         os << "[m]";
3245                         break;
3246                 case MINIPAGE_ALIGN_BOTTOM:
3247                         os << "[b]";
3248                         break;
3249                 }
3250                 if (!params.pextraWidth().empty()) {
3251                         os << '{' << params.pextraWidth() << "}\n";
3252                 } else {
3253                         //float ib = atof(par->pextra_width.c_str())/100;
3254                         // string can't handle floats at present
3255                         // so I'll do a conversion by hand knowing that
3256                         // the limits are 0.0 to 1.0. ARRae.
3257                         os << '{';
3258                         switch (params.pextraWidthp().length()) {
3259                         case 3:
3260                                 os << "1.00";
3261                                 break;
3262                         case 2:
3263                                 os << "0."
3264                                    << params.pextraWidthp();
3265                                 break;
3266                         case 1:
3267                                 os << "0.0"
3268                                    << params.pextraWidthp();
3269                         }
3270                         os << "\\columnwidth}\n";
3271                 }
3272                 texrow.newline();
3273                 if (par_sep == BufferParams::PARSEP_INDENT) {
3274                         os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3275                         texrow.newline();
3276                 }
3277                 minipage_open = true;
3278                 minipage_open_depth = params.depth();
3279         }
3280 #endif
3281 #ifdef WITH_WARNINGS
3282 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3283         //I disabled it because it breaks when lists span on several
3284         //pages (JMarc)
3285 #endif
3286         if (style.isEnvironment()){
3287                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3288 #ifdef FANCY_FOOTNOTE_CODE
3289                         if (foot_count < 0) {
3290                                 // flag that footnote[mark][text] should be
3291                                 // used for any footnotes from now on
3292                                 foot_count = 0;
3293                                 foot_this_level = true;
3294                         }
3295 #endif
3296                         os << "\\begin{" << style.latexname() << "}{"
3297                            << params.labelWidthString() << "}\n";
3298                 } else if (style.labeltype == LABEL_BIBLIO) {
3299                         // ale970405
3300                         os << "\\begin{" << style.latexname() << "}{"
3301                            <<  bibitemWidest(buf)
3302                            << "}\n";
3303                 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3304 #ifdef FANCY_FOOTNOTE_CODE
3305                         if (foot_count < 0) {
3306                                 // flag that footnote[mark][text] should be
3307                                 // used for any footnotes from now on
3308                                 foot_count = 0;
3309                                 foot_this_level = true;
3310                         }
3311 #endif
3312                         os << "\\begin{" << style.latexname() << '}'
3313                            << style.latexparam() << '\n';
3314                 } else 
3315                         os << "\\begin{" << style.latexname() << '}'
3316                            << style.latexparam() << '\n';
3317                 texrow.newline();
3318         }
3319         LyXParagraph * par = this;
3320         do {
3321                 par = par->TeXOnePar(buf, bparams,
3322                                      os, texrow, false
3323 #ifndef NEW_INSETS
3324                                      ,
3325                                      foot, foot_texrow, foot_count
3326 #endif
3327                         );
3328 #ifndef NO_PEXTRA
3329                 if (minipage_open && par && !style.isEnvironment() &&
3330                     (par->params.pextraType() == PEXTRA_MINIPAGE) &&
3331                     par->params.pextraStartMinipage()) {
3332                         os << "\\end{minipage}\n";
3333                         texrow.newline();
3334                         if (par_sep == BufferParams::PARSEP_INDENT) {
3335                                 os << "}\n";
3336                                 texrow.newline();
3337                         }
3338                         minipage_open = false;
3339                 }
3340 #endif
3341                 if (par && par->params.depth() > params.depth()) {
3342                         if (textclasslist.Style(bparams.textclass,
3343                                                 par->layout).isParagraph()
3344                             // Thinko!
3345                             // How to handle this? (Lgb)
3346                             //&& !suffixIs(os, "\n\n")
3347                                 ) {
3348                                 // There should be at least one '\n' already
3349                                 // but we need there to be two for Standard 
3350                                 // paragraphs that are depth-increment'ed to be
3351                                 // output correctly.  However, tables can
3352                                 // also be paragraphs so don't adjust them.
3353                                 // ARRae
3354                                 // Thinkee:
3355                                 // Will it ever harm to have one '\n' too
3356                                 // many? i.e. that we sometimes will have
3357                                 // three in a row. (Lgb)
3358                                 os << '\n';
3359                                 texrow.newline();
3360                         }
3361                         par = par->TeXDeeper(buf, bparams, os, texrow
3362 #ifndef NEW_INSETS
3363                                              ,foot, foot_texrow, foot_count
3364 #endif
3365                                 );
3366                 }
3367 #ifndef NO_PEXTRA
3368                 if (par && par->layout == layout && par->params.depth() == params.depth() &&
3369                     (par->params.pextraType() == PEXTRA_MINIPAGE) && !minipage_open) {
3370                         if (par->params.pextraHfill() && par->previous() &&
3371                             (par->previous()->params.pextraType() == PEXTRA_MINIPAGE)){
3372                                 os << "\\hfill{}\n";
3373                                 texrow.newline();
3374                         }
3375                         if (par_sep == BufferParams::PARSEP_INDENT) {
3376                                 os << "{\\setlength\\parindent{0pt}\n";
3377                                 texrow.newline();
3378                         }
3379                         os << "\\begin{minipage}";
3380                         switch (par->params.pextraAlignment()) {
3381                         case MINIPAGE_ALIGN_TOP:
3382                                 os << "[t]";
3383                                 break;
3384                         case MINIPAGE_ALIGN_MIDDLE:
3385                                 os << "[m]";
3386                                 break;
3387                         case MINIPAGE_ALIGN_BOTTOM:
3388                                 os << "[b]";
3389                                 break;
3390                         }
3391                         if (!par->params.pextraWidth().empty()) {
3392                                 os << '{' << par->params.pextraWidth() << "}\n";
3393                         } else {
3394                                 //float ib = atof(par->pextra_widthp.c_str())/100;
3395                                 // string can't handle floats at present
3396                                 // so I'll do a conversion by hand knowing that
3397                                 // the limits are 0.0 to 1.0. ARRae.
3398                                 os << '{';
3399                                 switch (par->params.pextraWidthp().length()) {
3400                                 case 3:
3401                                         os << "1.00";
3402                                         break;
3403                                 case 2:
3404                                         os << "0." << par->params.pextraWidthp();
3405                                         break;
3406                                 case 1:
3407                                         os << "0.0" << par->params.pextraWidthp();
3408                                 }
3409                                 os << "\\columnwidth}\n";
3410                         }
3411                         texrow.newline();
3412                         if (par_sep == BufferParams::PARSEP_INDENT) {
3413                                 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3414                                 texrow.newline();
3415                         }
3416                         minipage_open = true;
3417                         minipage_open_depth = par->params.depth();
3418                 }
3419 #endif
3420         } while (par
3421                  && par->layout == layout
3422                  && par->params.depth() == params.depth()
3423 #ifndef NO_PEXTRA
3424                  && par->params.pextraType() == params.pextraType()
3425 #endif
3426 #ifndef NEW_INSETS
3427                  && par->footnoteflag == footnoteflag
3428 #endif
3429                 );
3430  
3431         if (style.isEnvironment()) {
3432                 os << "\\end{" << style.latexname() << "}\n";
3433
3434 #ifndef NEW_INSETS
3435                 // maybe this should go after the minipage closes?
3436                 if (foot_this_level) {
3437                         if (foot_count >= 1) {
3438                                 if (foot_count > 1) {
3439                                         os << "\\addtocounter{footnote}{-"
3440                                            << foot_count - 1
3441                                            << '}';
3442                                 }
3443                                 os << foot;
3444                                 texrow += foot_texrow;
3445                                 foot.clear();
3446                                 foot_texrow.reset();
3447                                 foot_count = 0;
3448                         }
3449                 }
3450 #endif
3451         }
3452 #ifndef NO_PEXTRA
3453         if (minipage_open && (minipage_open_depth == params.depth()) &&
3454             (!par || par->params.pextraStartMinipage() ||
3455              par->params.pextraType() != PEXTRA_MINIPAGE)) {
3456                 os << "\\end{minipage}\n";
3457                 texrow.newline();
3458                 if (par_sep == BufferParams::PARSEP_INDENT) {
3459                         os << "}\n";
3460                         texrow.newline();
3461                 }
3462                 if (par && par->params.pextraType() != PEXTRA_MINIPAGE) {
3463                         os << "\\medskip\n\n";
3464                         texrow.newline();
3465                         texrow.newline();
3466                 }
3467                 minipage_open = false;
3468         }
3469         if (eindent_open) {
3470                 os << "\\end{LyXParagraphIndent}\n";
3471                 texrow.newline();
3472         }
3473         if (!(par && (par->params.pextraType() == PEXTRA_MINIPAGE) 
3474               && par->params.pextraHfill())) {
3475                 os << '\n';
3476                 texrow.newline();
3477         }
3478 #endif
3479         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3480         return par;  // ale970302
3481 }
3482
3483
3484 #ifndef NEW_INSETS
3485 LyXParagraph * LyXParagraph::TeXFootnote(Buffer const * buf,
3486                                          BufferParams const & bparams,
3487                                          ostream & os, TexRow & texrow,
3488                                          ostream & foot, TexRow & foot_texrow,
3489                                          int & foot_count,
3490                                          bool parent_is_rtl)
3491 {
3492         lyxerr[Debug::LATEX] << "TeXFootnote...  " << this << endl;
3493         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3494                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3495                         "No footnote!" << endl;
3496
3497         LyXParagraph * par = this;
3498         LyXLayout const & style =
3499                 textclasslist.Style(bparams.textclass, 
3500                                     previous_->GetLayout());
3501         
3502         if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3503                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3504                         "Float other than footnote in command"
3505                         " with moving argument is illegal" << endl;
3506         }
3507
3508         if (footnotekind != LyXParagraph::FOOTNOTE
3509             && footnotekind != LyXParagraph::MARGIN
3510             && os.tellp()
3511             // Thinko
3512             // How to solve this?
3513             //&& !suffixIs(file, '\n')
3514                 ) {
3515                 // we need to ensure that real floats like tables and figures
3516                 // have their \begin{} on a new line otherwise we can get
3517                 // incorrect results when using the endfloat.sty package
3518                 // especially if two floats follow one another.  ARRae 981022
3519                 // NOTE: if the file is length 0 it must have just been
3520                 //       written out so we assume it ended with a '\n'
3521                 // Thinkee:
3522                 // As far as I can see there is never any harm in writing
3523                 // a '\n' too much. Please tell me if I am wrong. (Lgb)
3524                 os << '\n';
3525                 texrow.newline();
3526         }
3527
3528         bool moving_arg = false;
3529         bool need_closing = false;
3530         bool is_rtl = isRightToLeftPar(bparams);
3531
3532         if (is_rtl != parent_is_rtl) {
3533                 if (is_rtl)
3534                         os << "\\R{";
3535                 else
3536                         os << "\\L{";
3537                 need_closing = true;
3538         }
3539         
3540         bool footer_in_body = true;
3541         switch (footnotekind) {
3542         case LyXParagraph::FOOTNOTE:
3543                 if (style.intitle) {
3544                         os << "\\thanks{\n";
3545                         footer_in_body = false;
3546                         moving_arg = true;
3547                 } else {
3548                         if (foot_count == -1) {
3549                                 // we're at depth 0 so we can use:
3550                                 os << "\\footnote{%\n";
3551                                 footer_in_body = false;
3552                         } else {
3553                                 os << "\\footnotemark{}%\n";
3554                                 if (foot_count) {
3555                                         // we only need this when there are
3556                                         // multiple footnotes
3557                                         os << "\\stepcounter{footnote}";
3558                                 }
3559                                 os << "\\footnotetext{%\n";
3560                                 foot_texrow.start(this, 0);
3561                                 foot_texrow.newline();
3562                                 ++foot_count;
3563                         }
3564                 }
3565                 break;
3566         case LyXParagraph::MARGIN:
3567                 os << "\\marginpar{\n";
3568                 break;
3569         case LyXParagraph::FIG:
3570                 if (params.pextraType() == PEXTRA_FLOATFLT
3571                     && (!params.pextraWidth().empty()
3572                         || !params.pextraWidthp().empty())) {
3573                         if (!params.pextraWidth().empty())
3574                                 os << "\\begin{floatingfigure}{"
3575                                    << params.pextraWidth() << "}\n";
3576                         else
3577                                 os << "\\begin{floatingfigure}{"
3578                                    << lyx::atoi(params.pextraWidthp()) / 100.0
3579                                    << "\\textwidth}\n";
3580                 } else {
3581                         os << "\\begin{figure}";
3582                         if (!bparams.float_placement.empty()) { 
3583                                 os << '[' << bparams.float_placement << "]\n";
3584                         } else {
3585                                 os << '\n';
3586                         }
3587                 }
3588                 break;
3589         case LyXParagraph::TAB:
3590                 os << "\\begin{table}";
3591                 if (!bparams.float_placement.empty()) { 
3592                         os << '[' << bparams.float_placement << "]\n";
3593                 } else {
3594                         os << '\n';
3595                 }
3596                 break;
3597         case LyXParagraph::WIDE_FIG:
3598                 os << "\\begin{figure*}";
3599                 if (!bparams.float_placement.empty()) { 
3600                         os << '[' << bparams.float_placement << "]\n";
3601                 } else {
3602                         os << '\n';
3603                 }
3604                 break;
3605         case LyXParagraph::WIDE_TAB:
3606                 os << "\\begin{table*}";
3607                 if (!bparams.float_placement.empty()) { 
3608                         os << '[' << bparams.float_placement << "]\n";
3609                 } else {
3610                         os << '\n';
3611                 }
3612                 break;
3613         case LyXParagraph::ALGORITHM:
3614                 os << "\\begin{algorithm}\n";
3615                 break;
3616         }
3617         texrow.newline();
3618    
3619         if (footnotekind != LyXParagraph::FOOTNOTE
3620             || !footer_in_body) {
3621                 // Process text for all floats except footnotes in body
3622                 do {
3623                         LyXLayout const & style =
3624                                 textclasslist
3625                                 .Style(bparams.textclass, par->layout);
3626                         if (par->IsDummy())
3627                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3628                                        << endl;
3629                         if (style.isEnvironment()
3630                             || par->params.pextraType() == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3631                                 // Allows the use of minipages within float
3632                                 // environments. Shouldn't be circular because
3633                                 // we don't support footnotes inside
3634                                 // floats (yet). ARRae
3635                                 par = par->TeXEnvironment(buf, bparams, os,
3636                                                           texrow,
3637                                                           foot, foot_texrow,
3638                                                           foot_count);
3639                         } else {
3640                                 par = par->TeXOnePar(buf, bparams,
3641                                                      os, texrow, moving_arg,
3642                                                      foot, foot_texrow,
3643                                                      foot_count);
3644                         }
3645                         
3646                         if (par && !par->IsDummy() && par->params.depth() > params.depth()) {
3647                                 par = par->TeXDeeper(buf, bparams, os, texrow,
3648                                                      foot, foot_texrow,
3649                                                      foot_count);
3650                         }
3651                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3652         } else {
3653                 // process footnotes > depth 0 or in environments separately
3654                 // NOTE: Currently don't support footnotes within footnotes
3655                 //       even though that is possible using the \footnotemark
3656                 std::ostringstream dummy;
3657                 TexRow dummy_texrow;
3658                 int dummy_count = 0;
3659                 do {
3660                         LyXLayout const & style =
3661                                 textclasslist
3662                                 .Style(bparams.textclass, par->layout);
3663                         if (par->IsDummy())
3664                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3665                                        << endl;
3666                         if (style.isEnvironment()
3667                             || par->params.pextraType() == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3668                                 // Allows the use of minipages within float
3669                                 // environments. Shouldn't be circular because
3670                                 // we don't support footnotes inside
3671                                 // floats (yet). ARRae
3672                                 par = par->TeXEnvironment(buf, bparams,
3673                                                           foot, foot_texrow,
3674                                                           dummy, dummy_texrow,
3675                                                           dummy_count);
3676                         } else {
3677                                 par = par->TeXOnePar(buf, bparams,
3678                                                      foot, foot_texrow,
3679                                                      moving_arg,
3680                                                      dummy, dummy_texrow,
3681                                                      dummy_count);
3682                         }
3683
3684                         if (par && !par->IsDummy() && par->params.depth() > params.depth()) {
3685                                 par = par->TeXDeeper(buf, bparams,
3686                                                      foot, foot_texrow,
3687                                                      dummy, dummy_texrow,
3688                                                      dummy_count);
3689                         }
3690                 } while (par
3691                          && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3692                 if (dummy_count) {
3693                         lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3694                                 "Footnote in a Footnote -- not supported"
3695                                << endl;
3696                 }
3697         }
3698
3699         switch (footnotekind) {
3700         case LyXParagraph::FOOTNOTE:
3701                 if (footer_in_body) {
3702                         // This helps tell which of the multiple
3703                         // footnotetexts an error was in.
3704                         foot << "}%\n";
3705                         foot_texrow.newline();
3706                 } else {
3707                         os << '}';
3708                 }
3709                 break;
3710         case LyXParagraph::MARGIN:
3711                 os << '}';
3712                 break;
3713         case LyXParagraph::FIG:
3714                 if (params.pextraType() == PEXTRA_FLOATFLT
3715                     && (!params.pextraWidth().empty()
3716                         || !params.pextraWidthp().empty()))
3717                         os << "\\end{floatingfigure}";
3718                 else
3719                         os << "\\end{figure}";
3720                 break;
3721         case LyXParagraph::TAB:
3722                 os << "\\end{table}";
3723                 break;
3724         case LyXParagraph::WIDE_FIG:
3725                 os << "\\end{figure*}";
3726                 break;
3727         case LyXParagraph::WIDE_TAB:
3728                 os << "\\end{table*}";
3729                 break;
3730         case LyXParagraph::ALGORITHM:
3731                 os << "\\end{algorithm}";
3732                 break;
3733         }
3734
3735         if (need_closing)
3736                 os << "}";
3737
3738         if (footnotekind != LyXParagraph::FOOTNOTE
3739             && footnotekind != LyXParagraph::MARGIN) {
3740                 // we need to ensure that real floats like tables and figures
3741                 // have their \end{} on a line of their own otherwise we can
3742                 // get incorrect results when using the endfloat.sty package.
3743                 os << "\n";
3744                 texrow.newline();
3745         }
3746
3747         lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next_ << endl;
3748         return par;
3749 }
3750
3751
3752 bool LyXParagraph::IsDummy() const
3753 {
3754         return (footnoteflag == LyXParagraph::NO_FOOTNOTE && previous_
3755                 && previous_->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3756 }
3757 #endif
3758
3759 #ifndef NO_PEXTRA
3760 void LyXParagraph::SetPExtraType(BufferParams const & bparams,
3761                                  int type, string const & width,
3762                                  string const & widthp)
3763 {
3764         params.pextraType(type);
3765         params.pextraWidth(width);
3766         params.pextraWidthp(widthp);
3767
3768         if (textclasslist.Style(bparams.textclass, 
3769                                 layout).isEnvironment()) {
3770                 LyXParagraph * par = this;
3771                 LyXParagraph * ppar = par;
3772
3773                 while (par && (par->layout == layout)
3774                        && (par->params.depth() == params.depth())) {
3775                         ppar = par;
3776                         par = par->previous();
3777 #ifndef NEW_INSETS
3778                         if (par)
3779                                 par = par->FirstPhysicalPar();
3780 #endif
3781                         while (par && par->params.depth() > params.depth()) {
3782                                 par = par->previous();
3783 #ifndef NEW_INSETS
3784                                 if (par)
3785                                         par = par->FirstPhysicalPar();
3786 #endif
3787                         }
3788                 }
3789                 par = ppar;
3790                 while (par && (par->layout == layout)
3791                        && (par->params.depth() == params.depth())) {
3792                         par->params.pextraType(type);
3793                         par->params.pextraWidth(width);
3794                         par->params.pextraWidthp(widthp);
3795 #ifndef NEW_INSETS
3796                         par = par->NextAfterFootnote();
3797 #else
3798                         par = par->next();
3799 #endif
3800                         if (par && (par->params.depth() > params.depth()))
3801                                 par->SetPExtraType(bparams,
3802                                                    type, width, widthp);
3803 #ifndef NEW_INSETS
3804                         while (par && ((par->params.depth() > params.depth()) || par->IsDummy()))
3805                                 par = par->NextAfterFootnote();
3806 #else
3807                         while (par && par->params.depth() > params.depth())
3808                                 par = par->next();
3809 #endif
3810                 }
3811         }
3812 }
3813
3814
3815 void LyXParagraph::UnsetPExtraType(BufferParams const & bparams)
3816 {
3817         if (params.pextraType() == PEXTRA_NONE)
3818                 return;
3819     
3820         params.pextraType(PEXTRA_NONE);
3821         params.pextraWidth(string());
3822         params.pextraWidthp(string());
3823
3824         if (textclasslist.Style(bparams.textclass, 
3825                                 layout).isEnvironment()) {
3826                 LyXParagraph * par = this;
3827                 LyXParagraph * ppar = par;
3828
3829                 while (par && (par->layout == layout)
3830                        && (par->params.depth() == params.depth())) {
3831                         ppar = par;
3832                         par = par->previous();
3833 #ifndef NEW_INSETS
3834                         if (par)
3835                                 par = par->FirstPhysicalPar();
3836 #endif
3837                         while (par && par->params.depth() > params.depth()) {
3838                                 par = par->previous();
3839 #ifndef NEW_INSETS
3840                                 if (par)
3841                                         par = par->FirstPhysicalPar();
3842 #endif
3843                         }
3844                 }
3845                 par = ppar;
3846                 while (par && (par->layout == layout)
3847                        && (par->params.depth() == params.depth())) {
3848                         par->params.pextraType(PEXTRA_NONE);
3849                         par->params.pextraWidth(string());
3850                         par->params.pextraWidthp(string());
3851 #ifndef NEW_INSETS
3852                         par = par->NextAfterFootnote();
3853 #else
3854                         par = par->next();
3855 #endif
3856                         if (par && (par->params.depth() > params.depth()))
3857                                 par->UnsetPExtraType(bparams);
3858 #ifndef NEW_INSETS
3859                         while (par && ((par->params.depth() > params.depth()) || par->IsDummy()))
3860                                 par = par->NextAfterFootnote();
3861 #else
3862                         while (par && par->params.depth() > params.depth())
3863                                 par = par->next();
3864 #endif
3865                 }
3866         }
3867 }
3868 #endif
3869
3870
3871 bool LyXParagraph::IsHfill(size_type pos) const
3872 {
3873         return IsHfillChar(GetChar(pos));
3874 }
3875
3876
3877 bool LyXParagraph::IsInset(size_type pos) const
3878 {
3879         return IsInsetChar(GetChar(pos));
3880 }
3881
3882
3883 #ifndef NEW_INSETS
3884 bool LyXParagraph::IsFloat(size_type pos) const
3885 {
3886         return IsFloatChar(GetChar(pos));
3887 }
3888 #endif
3889
3890
3891 bool LyXParagraph::IsNewline(size_type pos) const
3892 {
3893         return pos >= 0 && IsNewlineChar(GetChar(pos));
3894 }
3895
3896
3897 bool LyXParagraph::IsSeparator(size_type pos) const
3898 {
3899         return IsSeparatorChar(GetChar(pos));
3900 }
3901
3902
3903 bool LyXParagraph::IsLineSeparator(size_type pos) const
3904 {
3905         return IsLineSeparatorChar(GetChar(pos));
3906 }
3907
3908
3909 bool LyXParagraph::IsKomma(size_type pos) const
3910 {
3911         return IsKommaChar(GetChar(pos));
3912 }
3913
3914
3915 /// Used by the spellchecker
3916 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
3917 {
3918         value_type const c = GetChar(pos);
3919         if (IsLetterChar(c))
3920                 return true;
3921         // '\0' is not a letter, allthough every string contains "" (below)
3922         if (c == '\0')
3923                 return false;
3924         // We want to pass the ' and escape chars to ispell
3925         string const extra = lyxrc.isp_esc_chars + '\'';
3926         char ch[2] = { c, 0 };
3927         return contains(extra, ch);
3928 }
3929  
3930  
3931 bool LyXParagraph::IsWord(size_type pos ) const
3932 {
3933         return IsWordChar(GetChar(pos)) ;
3934 }
3935
3936
3937 Language const *
3938 LyXParagraph::getParLanguage(BufferParams const & bparams) const 
3939 {
3940 #ifndef NEW_INSETS
3941         if (IsDummy())
3942                 return FirstPhysicalPar()->getParLanguage(bparams);
3943         else
3944 #endif
3945         if (size() > 0)
3946                 return GetFirstFontSettings().language();
3947         else if (previous_)
3948                 return previous_->getParLanguage(bparams);
3949         else
3950                 return bparams.language;
3951 }
3952
3953
3954 bool LyXParagraph::isRightToLeftPar(BufferParams const & bparams) const
3955 {
3956         return lyxrc.rtl_support
3957                 && getParLanguage(bparams)->RightToLeft();
3958 }
3959
3960
3961 void LyXParagraph::ChangeLanguage(BufferParams const & bparams,
3962                                   Language const * from, Language const * to)
3963 {
3964         for (size_type i = 0; i < size(); ++i) {
3965                 LyXFont font = GetFontSettings(bparams, i);
3966                 if (font.language() == from) {
3967                         font.setLanguage(to);
3968                         SetFont(i, font);
3969                 }
3970         }
3971 }
3972
3973
3974 bool LyXParagraph::isMultiLingual(BufferParams const & bparams)
3975 {
3976         Language const * doc_language = bparams.language;
3977         for (FontList::const_iterator cit = fontlist.begin();
3978              cit != fontlist.end(); ++cit)
3979                 if ((*cit).font().language() != doc_language)
3980                         return true;
3981         return false;
3982 }
3983
3984
3985 // Convert the paragraph to a string.
3986 // Used for building the table of contents
3987 string const LyXParagraph::String(Buffer const * buffer, bool label)
3988 {
3989         BufferParams const & bparams = buffer->params;
3990         string s;
3991 #ifndef NEW_INSETS
3992         if (label && !IsDummy() && !params.labelString().empty())
3993 #else
3994         if (label && !params.labelString().empty())
3995 #endif
3996                 s += params.labelString() + ' ';
3997         string::size_type const len = s.size();
3998
3999         for (LyXParagraph::size_type i = 0; i < size(); ++i) {
4000                 value_type c = GetChar(i);
4001                 if (IsPrintable(c))
4002                         s += c;
4003                 else if (c == META_INSET &&
4004                          GetInset(i)->LyxCode() == Inset::MATH_CODE) {
4005                         std::ostringstream ost;
4006                         GetInset(i)->Ascii(buffer, ost);
4007                         s += subst(ost.str().c_str(),'\n',' ');
4008                 }
4009         }
4010
4011 #ifndef NEW_INSETS
4012         if (next_ && next_->footnoteflag != LyXParagraph::NO_FOOTNOTE 
4013             && footnoteflag == LyXParagraph::NO_FOOTNOTE)
4014                 s += NextAfterFootnote()->String(buffer, false);
4015
4016         if (!IsDummy()) {
4017 #endif
4018                 if (isRightToLeftPar(bparams))
4019                         reverse(s.begin() + len,s.end());
4020 #ifndef NEW_INSETS
4021         }
4022 #endif
4023         return s;
4024 }
4025
4026
4027 string const LyXParagraph::String(Buffer const * buffer, 
4028                             LyXParagraph::size_type beg,
4029                             LyXParagraph::size_type end)
4030 {
4031         string s;
4032
4033 #ifndef NEW_INSETS
4034         if (beg == 0 && !IsDummy() && !params.labelString().empty())
4035 #else
4036         if (beg == 0 && !params.labelString().empty())
4037 #endif
4038                 s += params.labelString() + ' ';
4039
4040         for (LyXParagraph::size_type i = beg; i < end; ++i) {
4041                 value_type c = GetUChar(buffer->params, i);
4042                 if (IsPrintable(c))
4043                         s += c;
4044                 else if (c == META_INSET) {
4045                         std::ostringstream ost;
4046                         GetInset(i)->Ascii(buffer, ost);
4047                         s += ost.str().c_str();
4048                 }
4049         }
4050
4051         return s;
4052 }
4053
4054
4055 void LyXParagraph::SetInsetOwner(Inset * i)
4056 {
4057         inset_owner = i;
4058         for (InsetList::const_iterator cit = insetlist.begin();
4059              cit != insetlist.end(); ++cit) {
4060                 if ((*cit).inset)
4061                         (*cit).inset->setOwner(i);
4062         }
4063 }
4064
4065
4066 void LyXParagraph::deleteInsetsLyXText(BufferView * bv)
4067 {
4068         // then the insets
4069         for (InsetList::const_iterator cit = insetlist.begin();
4070              cit != insetlist.end(); ++cit) {
4071                 if ((*cit).inset) {
4072                         if ((*cit).inset->IsTextInset()) {
4073                                 static_cast<UpdatableInset *>
4074                                         ((*cit).inset)->deleteLyXText(bv);
4075                         }
4076                 }
4077         }
4078 }
4079
4080
4081 void LyXParagraph::resizeInsetsLyXText(BufferView * bv)
4082 {
4083         // then the insets
4084         for (InsetList::const_iterator cit = insetlist.begin();
4085              cit != insetlist.end(); ++cit) {
4086                 if ((*cit).inset) {
4087                         if ((*cit).inset->IsTextInset()) {
4088                                 static_cast<UpdatableInset *>
4089                                         ((*cit).inset)->resizeLyXText(bv);
4090                         }
4091                 }
4092         }
4093 }
4094
4095
4096 void LyXParagraph::fitToSize()
4097 {
4098         TextContainer tmp(text.begin(), text.end());
4099         text.swap(tmp);
4100 }
4101
4102
4103 void LyXParagraph::setContentsFromPar(LyXParagraph * par)
4104 {
4105         text = par->text;
4106 }