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