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