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