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