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