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