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