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