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