]> git.lyx.org Git - lyx.git/blob - src/paragraph.C
73ef0be674ea861d7f54e88515812ce890b5599d
[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
37
38 extern void addNewlineAndDepth(string & file, int depth); // Jug 990923
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
1208
1209 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1210 {
1211         if (!IsDummy())
1212                 return this;
1213         LyXParagraph * tmppar = this;
1214
1215         while (tmppar &&
1216                (tmppar->IsDummy()
1217                 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1218                 tmppar = tmppar->previous;
1219    
1220         if (!tmppar) {
1221                 return this;
1222         } else
1223                 return tmppar;
1224 }
1225
1226
1227 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1228 {
1229         if (!IsDummy())
1230                 return this;
1231         LyXParagraph const * tmppar = this;
1232
1233         while (tmppar &&
1234                (tmppar->IsDummy()
1235                 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1236                 tmppar = tmppar->previous;
1237    
1238         if (!tmppar) {
1239                 return this;
1240         } else
1241                 return tmppar;
1242 }
1243
1244
1245 // This function is able to hide closed footnotes.
1246 LyXParagraph * LyXParagraph::Previous()
1247 {
1248         LyXParagraph * tmp = previous;
1249         if (!tmp)
1250                 return tmp;
1251    
1252         if (tmp->previous
1253             && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1254                 tmp = tmp->previous;
1255                 while (tmp
1256                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1257                         tmp = tmp->previous;
1258                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1259                         return tmp->next->Previous();   
1260
1261                 else
1262                         return previous; 
1263         } else
1264                 return previous;
1265 }
1266
1267
1268 // This function is able to hide closed footnotes.
1269 LyXParagraph const * LyXParagraph::Previous() const
1270 {
1271         LyXParagraph * tmp = previous;
1272         if (!tmp)
1273                 return tmp;
1274    
1275         if (tmp->previous
1276             && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1277                 tmp = tmp->previous;
1278                 while (tmp
1279                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1280                         tmp = tmp->previous;
1281                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1282                         return tmp->next->Previous();   
1283
1284                 else
1285                         return previous; 
1286         } else
1287                 return previous;
1288 }
1289
1290
1291 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1292                                   int flag)
1293 {
1294         size_type i, pos_end, pos_first;
1295         // create a new paragraph
1296         LyXParagraph * par = ParFromPos(pos);
1297         LyXParagraph * firstpar = FirstPhysicalPar();
1298    
1299         LyXParagraph * tmp = new LyXParagraph(par);
1300         
1301         tmp->footnoteflag = footnoteflag;
1302         tmp->footnotekind = footnotekind;
1303    
1304         // this is an idea for a more userfriendly layout handling, I will
1305         // see what the users say
1306    
1307         // layout stays the same with latex-environments
1308         if (flag) {
1309                 tmp->SetOnlyLayout(firstpar->layout);
1310                 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1311         }
1312
1313         if (Last() > pos || !Last() || flag == 2) {
1314                 tmp->SetOnlyLayout(firstpar->layout);
1315                 tmp->align = firstpar->align;
1316                 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1317       
1318                 tmp->line_bottom = firstpar->line_bottom;
1319                 firstpar->line_bottom = false;
1320                 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1321                 firstpar->pagebreak_bottom = false;
1322                 tmp->added_space_bottom = firstpar->added_space_bottom;
1323                 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1324       
1325                 tmp->depth = firstpar->depth;
1326                 tmp->noindent = firstpar->noindent;
1327    
1328                 // copy everything behind the break-position
1329                 // to the new paragraph
1330                 pos_first = 0;
1331                 while (ParFromPos(pos_first) != par)
1332                         ++pos_first;
1333
1334                 pos_end = pos_first + par->text.size() - 1;
1335                 // The constructor has already reserved 500 elements
1336                 //if (pos_end > pos)
1337                 //      tmp->text.reserve(pos_end - pos);
1338
1339                 for (i = pos; i <= pos_end; ++i) {
1340                         par->CutIntoMinibuffer(i - pos_first);
1341                         tmp->InsertFromMinibuffer(i - pos);
1342                 }
1343                 tmp->text.resize(tmp->text.size());
1344                 for (i = pos_end; i >= pos; --i)
1345                         par->Erase(i - pos_first);
1346
1347                 par->text.resize(par->text.size());
1348         }
1349
1350         // just an idea of me
1351         if (!pos) {
1352                 tmp->line_top = firstpar->line_top;
1353                 tmp->pagebreak_top = firstpar->pagebreak_top;
1354                 tmp->added_space_top = firstpar->added_space_top;
1355                 tmp->bibkey = firstpar->bibkey;
1356                 firstpar->Clear();
1357                 // layout stays the same with latex-environments
1358                 if (flag) {
1359                         firstpar->SetOnlyLayout(tmp->layout);
1360                         firstpar->SetLabelWidthString(tmp->labelwidthstring);
1361                         firstpar->depth = tmp->depth;
1362                 }
1363         }
1364 }
1365
1366
1367 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1368 {
1369         par = par->FirstPhysicalPar();
1370         footnoteflag = par->footnoteflag;
1371         footnotekind = par->footnotekind;
1372
1373         layout = par->layout;
1374         align = par-> align;
1375         SetLabelWidthString(par->labelwidthstring);
1376
1377         line_bottom = par->line_bottom;
1378         pagebreak_bottom = par->pagebreak_bottom;
1379         added_space_bottom = par->added_space_bottom;
1380
1381         line_top = par->line_top;
1382         pagebreak_top = par->pagebreak_top;
1383         added_space_top = par->added_space_top;
1384
1385         pextra_type = par->pextra_type;
1386         pextra_width = par->pextra_width;
1387         pextra_widthp = par->pextra_widthp;
1388         pextra_alignment = par->pextra_alignment;
1389         pextra_hfill = par->pextra_hfill;
1390         pextra_start_minipage = par->pextra_start_minipage;
1391
1392         noindent = par->noindent;
1393         depth = par->depth;
1394 }
1395
1396
1397 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1398 {
1399         LyXParagraph * tmppar = this;
1400         while (tmppar && (
1401                 (tmppar->IsDummy()
1402                  && tmppar->previous->footnoteflag == 
1403                  LyXParagraph::CLOSED_FOOTNOTE)
1404                 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1405                 tmppar = tmppar->previous;
1406    
1407         if (!tmppar)
1408                 return this;  // This should never happen!
1409         else
1410                 return tmppar;
1411 }
1412
1413
1414 LyXParagraph * LyXParagraph::Clone() const
1415 {
1416         // create a new paragraph
1417         LyXParagraph * result = new LyXParagraph;
1418    
1419         result->MakeSameLayout(this);
1420
1421         // this is because of the dummy layout of the paragraphs that
1422         // follow footnotes
1423         result->layout = layout;
1424    
1425         /* table stuff -- begin*/ 
1426         if (table)
1427                 result->table = table->Clone();
1428         else
1429                 result->table = 0;
1430         /* table stuff -- end*/ 
1431    
1432         // ale970302
1433         result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1434                
1435     
1436         // copy everything behind the break-position to the new paragraph
1437    
1438         for (size_type i = 0; i < size(); ++i) {
1439                 CopyIntoMinibuffer(i);
1440                 result->InsertFromMinibuffer(i);
1441         }
1442         result->text.resize(result->text.size());
1443         return result;
1444 }
1445
1446
1447 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1448 {
1449         par = par->FirstPhysicalPar();
1450
1451         return (
1452                 par->footnoteflag == footnoteflag &&
1453                 par->footnotekind == footnotekind &&
1454
1455                 par->layout == layout &&
1456
1457                 par->align == align &&
1458
1459                 par->line_bottom == line_bottom &&
1460                 par->pagebreak_bottom == pagebreak_bottom &&
1461                 par->added_space_bottom == added_space_bottom &&
1462
1463                 par->line_top == line_top &&
1464                 par->pagebreak_top == pagebreak_top &&
1465                 par->added_space_top == added_space_top &&
1466
1467                 par->pextra_type == pextra_type &&
1468                 par->pextra_width == pextra_width && 
1469                 par->pextra_widthp == pextra_widthp && 
1470                 par->pextra_alignment == pextra_alignment && 
1471                 par->pextra_hfill == pextra_hfill && 
1472                 par->pextra_start_minipage == pextra_start_minipage && 
1473
1474                 par->table == table && // what means: NO TABLE AT ALL 
1475
1476                 par->noindent == noindent &&
1477                 par->depth == depth);
1478 }
1479
1480
1481 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1482 {
1483         // create a new paragraph
1484         LyXParagraph * par = ParFromPos(pos);
1485
1486         LyXParagraph * tmp = new LyXParagraph(par);
1487    
1488         tmp->MakeSameLayout(par);
1489
1490         // When can pos < Last()?
1491         // I guess pos == Last() is possible.
1492         if (Last() > pos) {
1493                 // copy everything behind the break-position to the new
1494                 // paragraph
1495                 size_type pos_first = 0;
1496                 while (ParFromPos(pos_first) != par)
1497                         ++pos_first;
1498                 size_type pos_end = pos_first + par->text.size() - 1;
1499                 // make sure there is enough memory for the now larger
1500                 // paragraph. This is not neccessary, because
1501                 // InsertFromMinibuffer will enlarge the memory (it uses
1502                 // InsertChar of course). But doing it by hand
1503                 // is MUCH faster! (only one time, not thousend times!!)
1504                 // Not needed since the constructor aleady have
1505                 // reserved 500 elements in text.
1506                 //if (pos_end > pos)
1507                 //      tmp->text.reserve(pos_end - pos);
1508
1509                 for (size_type i = pos; i <= pos_end; ++i) {
1510                         par->CutIntoMinibuffer(i - pos_first);
1511                         tmp->InsertFromMinibuffer(i - pos);
1512                 }
1513                 tmp->text.resize(tmp->text.size());
1514                 for (size_type i = pos_end; i >= pos; --i)
1515                         par->Erase(i - pos_first);
1516
1517                 par->text.resize(par->text.size());
1518         }
1519 }
1520    
1521
1522 // Be carefull, this does not make any check at all.
1523 void LyXParagraph::PasteParagraph()
1524 {
1525         // copy the next paragraph to this one
1526         LyXParagraph * the_next = Next();
1527    
1528         LyXParagraph * firstpar = FirstPhysicalPar();
1529    
1530         // first the DTP-stuff
1531         firstpar->line_bottom = the_next->line_bottom;
1532         firstpar->added_space_bottom = the_next->added_space_bottom;
1533         firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1534
1535         size_type pos_end = the_next->text.size() - 1;
1536         size_type pos_insert = Last();
1537
1538         // ok, now copy the paragraph
1539         for (size_type i = 0; i <= pos_end; ++i) {
1540                 the_next->CutIntoMinibuffer(i);
1541                 InsertFromMinibuffer(pos_insert + i);
1542         }
1543    
1544         // delete the next paragraph
1545         delete the_next;
1546 }
1547
1548
1549 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1550 {
1551         LyXParagraph * par = ParFromPos(pos);
1552         par = par->next;
1553         while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1554                 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1555                 par = par->next;
1556         }
1557 }
1558
1559
1560 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1561 {
1562         LyXParagraph * par = ParFromPos(pos);
1563         par = par->next;
1564         while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1565                 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1566                 par = par->next;
1567         }
1568 }
1569
1570
1571 LyXTextClass::size_type LyXParagraph::GetLayout() const
1572 {
1573         return FirstPhysicalPar()->layout;
1574 }
1575
1576
1577 char LyXParagraph::GetDepth() const
1578 {
1579         return FirstPhysicalPar()->depth;
1580 }
1581
1582
1583 char LyXParagraph::GetAlign() const
1584 {
1585         return FirstPhysicalPar()->align;
1586 }
1587
1588
1589 string LyXParagraph::GetLabestring() const
1590 {
1591         return FirstPhysicalPar()->labelstring;
1592 }
1593
1594
1595 int LyXParagraph::GetFirstCounter(int i) const
1596 {
1597         return FirstPhysicalPar()->counter_[i];
1598 }
1599
1600
1601 // the next two functions are for the manual labels
1602 string LyXParagraph::GetLabelWidthString() const
1603 {
1604         if (!FirstPhysicalPar()->labelwidthstring.empty())
1605                 return FirstPhysicalPar()->labelwidthstring;
1606         else
1607                 return _("Senseless with this layout!");
1608 }
1609
1610
1611 void LyXParagraph::SetLabelWidthString(string const & s)
1612 {
1613         LyXParagraph * par = FirstPhysicalPar();
1614
1615         par->labelwidthstring = s;
1616 }
1617
1618
1619 void LyXParagraph::SetOnlyLayout(LyXTextClass::size_type new_layout)
1620 {
1621         LyXParagraph * par = FirstPhysicalPar();
1622         LyXParagraph * ppar = 0;
1623         LyXParagraph * npar = 0;
1624
1625         par->layout = new_layout;
1626         /* table stuff -- begin*/ 
1627         if (table) 
1628                 par->layout = 0;
1629         /* table stuff -- end*/ 
1630         if (par->pextra_type == PEXTRA_NONE) {
1631                 if (par->Previous()) {
1632                         ppar = par->Previous()->FirstPhysicalPar();
1633                         while(ppar
1634                               && ppar->Previous()
1635                               && (ppar->depth > par->depth))
1636                                 ppar = ppar->Previous()->FirstPhysicalPar();
1637                 }
1638                 if (par->Next()) {
1639                         npar = par->Next()->NextAfterFootnote();
1640                         while(npar
1641                               && npar->Next()
1642                               && (npar->depth > par->depth))
1643                                 npar = npar->Next()->NextAfterFootnote();
1644                 }
1645                 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1646                         string
1647                                 p1 = ppar->pextra_width,
1648                                 p2 = ppar->pextra_widthp;
1649                         ppar->SetPExtraType(ppar->pextra_type,
1650                                             p1.c_str(), p2.c_str());
1651                 }
1652                 if ((par->pextra_type == PEXTRA_NONE) &&
1653                     npar && (npar->pextra_type != PEXTRA_NONE)) {
1654                         string
1655                                 p1 = npar->pextra_width,
1656                                 p2 = npar->pextra_widthp;
1657                         npar->SetPExtraType(npar->pextra_type,
1658                                             p1.c_str(), p2.c_str());
1659                 }
1660         }
1661 }
1662
1663
1664 void LyXParagraph::SetLayout(LyXTextClass::size_type new_layout)
1665 {
1666         LyXParagraph
1667                 * par = FirstPhysicalPar(),
1668                 * ppar = 0,
1669                 * npar = 0;
1670
1671         par->layout = new_layout;
1672         par->labelwidthstring.clear();
1673         par->align = LYX_ALIGN_LAYOUT;
1674         par->added_space_top = VSpace(VSpace::NONE);
1675         par->added_space_bottom = VSpace(VSpace::NONE);
1676         /* table stuff -- begin*/ 
1677         if (table) 
1678                 par->layout = 0;
1679         /* table stuff -- end*/
1680         if (par->pextra_type == PEXTRA_NONE) {
1681                 if (par->Previous()) {
1682                         ppar = par->Previous()->FirstPhysicalPar();
1683                         while(ppar
1684                               && ppar->Previous()
1685                               && (ppar->depth > par->depth))
1686                                 ppar = ppar->Previous()->FirstPhysicalPar();
1687                 }
1688                 if (par->Next()) {
1689                         npar = par->Next()->NextAfterFootnote();
1690                         while(npar
1691                               && npar->Next()
1692                               && (npar->depth > par->depth))
1693                                 npar = npar->Next()->NextAfterFootnote();
1694                 }
1695                 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1696                         string
1697                                 p1 = ppar->pextra_width,
1698                                 p2 = ppar->pextra_widthp;
1699                         ppar->SetPExtraType(ppar->pextra_type,
1700                                             p1.c_str(), p2.c_str());
1701                 }
1702                 if ((par->pextra_type == PEXTRA_NONE) &&
1703                     npar && (npar->pextra_type != PEXTRA_NONE)) {
1704                         string
1705                                 p1 = npar->pextra_width,
1706                                 p2 = npar->pextra_widthp;
1707                         npar->SetPExtraType(npar->pextra_type,
1708                                             p1.c_str(), p2.c_str());
1709                 }
1710         }
1711 }
1712
1713
1714 // if the layout of a paragraph contains a manual label, the beginning of the 
1715 // main body is the beginning of the second word. This is what the par-
1716 // function returns. If the layout does not contain a label, the main
1717 // body always starts with position 0. This differentiation is necessary,
1718 // because there cannot be a newline or a blank <= the beginning of the 
1719 // main body in TeX.
1720
1721 int LyXParagraph::BeginningOfMainBody() const
1722 {
1723         if (FirstPhysicalPar() != this)
1724                 return -1;
1725    
1726         // Unroll the first two cycles of the loop
1727         // and remember the previous character to
1728         // remove unnecessary GetChar() calls
1729         size_type i = 0;
1730         if (i < size()
1731             && GetChar(i) != LyXParagraph::META_NEWLINE
1732                 ) {
1733                 ++i;
1734                 char previous_char, temp;
1735                 if (i < size()
1736                     && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1737                         // Yes, this  ^ is supposed to be "= " not "=="
1738                         ++i;
1739                         while (i < size()
1740                                && previous_char != ' '
1741                                && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1742                                 ++i;
1743                                 previous_char = temp;
1744                         }
1745                 }
1746         }
1747
1748         if (i == 0 && i == size() &&
1749             !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1750               && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1751                 ++i;                           /* the cursor should not jump  
1752                                                 * to the main body if there
1753                                                 * is nothing in! */
1754         return i;
1755 }
1756
1757
1758 LyXParagraph * LyXParagraph::DepthHook(int deth)
1759 {
1760         LyXParagraph * newpar = this;
1761         if (deth < 0)
1762                 return 0;
1763    
1764         do {
1765                 newpar = newpar->FirstPhysicalPar()->Previous();
1766         } while (newpar && newpar->GetDepth() > deth
1767                  && newpar->footnoteflag == footnoteflag);
1768    
1769         if (!newpar) {
1770                 if (Previous() || GetDepth())
1771                         lyxerr << "ERROR (LyXParagraph::DepthHook): "
1772                                 "no hook." << endl;
1773                 newpar = this;
1774         }
1775         return newpar->FirstPhysicalPar();
1776 }
1777
1778
1779 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1780 {
1781         LyXParagraph const * newpar = this;
1782         if (deth < 0)
1783                 return 0;
1784    
1785         do {
1786                 newpar = newpar->FirstPhysicalPar()->Previous();
1787         } while (newpar && newpar->GetDepth() > deth
1788                  && newpar->footnoteflag == footnoteflag);
1789    
1790         if (!newpar) {
1791                 if (Previous() || GetDepth())
1792                         lyxerr << "ERROR (LyXParagraph::DepthHook): "
1793                                 "no hook." << endl;
1794                 newpar = this;
1795         }
1796         return newpar->FirstPhysicalPar();
1797 }
1798
1799
1800 int LyXParagraph::AutoDeleteInsets()
1801 {
1802         vector<size_type> tmpvec;
1803         int i = 0;
1804         for (InsetList::iterator it = insetlist.begin();
1805              it != insetlist.end(); ++it) {
1806                 if ((*it).inset && (*it).inset->AutoDelete()) {
1807                         tmpvec.push_back((*it).pos);
1808                         ++i;
1809                 }
1810         }
1811         for (vector<size_type>::const_iterator cit = tmpvec.begin();
1812              cit != tmpvec.end(); ++cit) {
1813                 Erase((*cit));
1814         }
1815         return i;
1816 }
1817
1818
1819 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
1820 {
1821         InsetList::iterator it2 = insetlist.end();
1822         for (InsetList::iterator it = insetlist.begin();
1823              it != insetlist.end(); ++it) {
1824                 if ((*it).pos >= pos) {
1825                         if (it2 == insetlist.end() || (*it).pos < (*it2).pos)
1826                                 it2 = it;
1827                 }
1828         }
1829         if (it2 != insetlist.end()) {
1830                 pos = (*it2).pos;
1831                 return (*it2).inset;
1832         }
1833         return 0;
1834 }
1835
1836
1837 // returns -1 if inset not found
1838 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1839 {
1840         // Find the entry.
1841         for (InsetList::const_iterator cit = insetlist.begin();
1842              cit != insetlist.end(); ++cit) {
1843                 if ((*cit).inset == inset) {
1844                         return (*cit).pos;
1845                 }
1846         }
1847         // Think about footnotes.
1848         if (footnoteflag == LyXParagraph::NO_FOOTNOTE 
1849             && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1850                 int further = 
1851                         NextAfterFootnote()->GetPositionOfInset(inset);
1852                 if (further != -1)
1853                         return text.size() + 1 + further;
1854         }
1855         return -1;
1856 }
1857
1858
1859 void LyXParagraph::readSimpleWholeFile(istream & is)
1860 {
1861         is.seekg(0);
1862         char c = 0;
1863         while(!is.eof()) {
1864                 is.get(c);
1865                 InsertChar(text.size(), c);
1866         };
1867 }
1868
1869
1870 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
1871                                        string & foot, TexRow & foot_texrow,
1872                                        int & foot_count)
1873 {
1874         lyxerr[Debug::LATEX] << "TeXOnePar...     " << this << endl;
1875         LyXParagraph * par = next;
1876         LyXLayout const & style =
1877                 textclasslist.Style(current_view->buffer()->params.textclass,
1878                                     layout);
1879
1880         bool further_blank_line = false;
1881         if (IsDummy())
1882                 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1883
1884         if (start_of_appendix) {
1885                 file += "\\appendix\n";
1886                 texrow.newline();
1887         }
1888
1889         if (tex_code_break_column && style.isCommand()){
1890                 file += '\n';
1891                 texrow.newline();
1892         }
1893
1894         if (pagebreak_top) {
1895                 file += "\\newpage";
1896                 further_blank_line = true;
1897         }
1898         if (added_space_top.kind() != VSpace::NONE) {
1899                 file += added_space_top.asLatexCommand(current_view->buffer()->params);
1900                 further_blank_line = true;
1901         }
1902       
1903         if (line_top) {
1904                 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
1905                 file += "\\vspace{-1\\parskip}";
1906                 further_blank_line = true;
1907         }
1908
1909         if (further_blank_line){
1910                 file += '\n';
1911                 texrow.newline();
1912         }
1913
1914         LyXDirection direction = getParDirection();
1915         LyXDirection global_direction =
1916                 current_view->buffer()->params.getDocumentDirection();
1917         if (direction != global_direction) {
1918                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1919                         file += "\\unsethebrew\n";
1920                 else
1921                         file += "\\sethebrew\n";
1922                 texrow.newline();
1923         }
1924         
1925
1926         switch (style.latextype) {
1927         case LATEX_COMMAND:
1928                 file += '\\';
1929                 file += style.latexname();
1930                 file += style.latexparam();
1931                 break;
1932         case LATEX_ITEM_ENVIRONMENT:
1933                 if (bibkey) 
1934                         bibkey->Latex(file, false);
1935                 else
1936                         file += "\\item ";
1937                 break;
1938         case LATEX_LIST_ENVIRONMENT:
1939                 file += "\\item ";
1940                 break;
1941         default:
1942                 break;
1943         }
1944
1945         bool need_par = SimpleTeXOnePar(file, texrow);
1946  
1947         // Spit out footnotes
1948         while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
1949                && par->footnoteflag != footnoteflag) {
1950                 par = par->TeXFootnote(file, texrow,
1951                                        foot, foot_texrow, foot_count,
1952                                        direction);
1953                 par->SimpleTeXOnePar(file, texrow);
1954                 par = par->next;
1955         }
1956
1957         // Make sure that \\par is done with the font of the last
1958         // character if this has another size as the default.
1959         // This is necessary because LaTeX (and LyX on the screen)
1960         // calculates the space between the baselines according
1961         // to this font. (Matthias)
1962         LyXFont font = getFont(Last()-1);
1963         if (need_par) {
1964                 if (style.resfont.size() != font.size()) {
1965                         file += '\\';
1966                         file += font.latexSize();
1967                         file += ' ';
1968                 }
1969                 file += "\\par}";
1970         } else if (textclasslist.Style(current_view->buffer()->params.textclass,
1971                                        GetLayout()).isCommand()){
1972                 if (style.resfont.size() != font.size()) {
1973                         file += '\\';
1974                         file += font.latexSize();
1975                         file += ' ';
1976                 }
1977                 file += '}';
1978         } else if (style.resfont.size() != font.size()){
1979                 file += "{\\" + font.latexSize() + " \\par}";
1980         }
1981
1982         if (direction != global_direction)
1983                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1984                         file += "\\sethebrew";
1985                 else
1986                         file += "\\unsethebrew";
1987         
1988         switch (style.latextype) {
1989         case LATEX_ITEM_ENVIRONMENT:
1990         case LATEX_LIST_ENVIRONMENT:
1991                 if (par && (depth < par->depth)) {
1992                         file += '\n';
1993                         texrow.newline();
1994                 }
1995                 break;
1996         case LATEX_ENVIRONMENT:
1997                 // if its the last paragraph of the current environment
1998                 // skip it otherwise fall through
1999                 if (par
2000                     && (par->layout != layout
2001                         || par->depth != depth
2002                         || par->pextra_type != pextra_type))
2003                         break;
2004         default:
2005                 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2006                       && footnotekind != LyXParagraph::FOOTNOTE
2007                       && footnotekind != LyXParagraph::MARGIN
2008                       && (table
2009                           || (par
2010                               && par->table)))) {
2011                         // don't insert this if we would be adding it
2012                         // before or after a table in a float.  This 
2013                         // little trick is needed in order to allow
2014                         // use of tables in \subfigures or \subtables.
2015                         file += '\n';
2016                         texrow.newline();
2017                 }
2018         }
2019         
2020         further_blank_line = false;
2021         if (line_bottom) {
2022                 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2023                 further_blank_line = true;
2024         }
2025
2026         if (added_space_bottom.kind() != VSpace::NONE) {
2027                 file += added_space_bottom.asLatexCommand(current_view->buffer()->params);
2028                 further_blank_line = true;
2029         }
2030       
2031         if (pagebreak_bottom) {
2032                 file += "\\newpage";
2033                 further_blank_line = true;
2034         }
2035
2036         if (further_blank_line){
2037                 file += '\n';
2038                 texrow.newline();
2039         }
2040
2041         if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2042               par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2043                 file += '\n';
2044                 texrow.newline();
2045         }
2046
2047         lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2048         return par;
2049 }
2050
2051
2052 // This one spits out the text of the paragraph
2053 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2054 {
2055         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...     " << this << endl;
2056
2057         if (table)
2058                 return SimpleTeXOneTablePar(file, texrow);
2059
2060         bool return_value = false;
2061
2062         LyXLayout const & style =
2063                 textclasslist.Style(current_view->buffer()->params.textclass,
2064                                     GetLayout());
2065         LyXFont basefont, last_font;
2066
2067         // Maybe we have to create a optional argument.
2068         size_type main_body;
2069         if (style.labeltype != LABEL_MANUAL)
2070                 main_body = 0;
2071         else
2072                 main_body = BeginningOfMainBody();
2073
2074         if (main_body > 0) {
2075                 file += '[';
2076                 basefont = getFont(-2); // Get label font
2077         } else {
2078                 basefont = getFont(-1); // Get layout font
2079         }
2080
2081         int column = 0;
2082
2083         if (main_body >= 0
2084             && !text.size()
2085             && !IsDummy()) {
2086                 if (style.isCommand()) {
2087                         file += '{';
2088                         ++column;
2089                 } else if (align != LYX_ALIGN_LAYOUT) {
2090                         file += '{';
2091                         ++column;
2092                         return_value = true;
2093                 }
2094         }
2095  
2096         // Which font is currently active?
2097         LyXFont running_font = basefont;
2098         // Do we have an open font change?
2099         bool open_font = false;
2100
2101         texrow.start(this, 0);
2102
2103         for (size_type i = 0; i < size(); ++i) {
2104                 ++column;
2105                 // First char in paragraph or after label?
2106                 if (i == main_body && !IsDummy()) {
2107                         if (main_body > 0) {
2108                                 if (open_font) {
2109                                         column += running_font.latexWriteEndChanges(file, basefont, basefont);
2110                                         open_font = false;
2111                                 }
2112                                 basefont = getFont(-1); // Now use the layout font
2113                                 running_font = basefont;
2114                                 file += ']';
2115                                 ++column;
2116                         }
2117                         if (style.isCommand()) {
2118                                 file += '{';
2119                                 ++column;
2120                         } else if (align != LYX_ALIGN_LAYOUT) {
2121                                 file += "{\\par";
2122                                 column += 4;
2123                                 return_value = true;
2124                         }
2125
2126                         if (noindent) {
2127                                 file += "\\noindent ";
2128                                 column += 10;
2129                         }
2130                         switch (align) {
2131                         case LYX_ALIGN_NONE:
2132                         case LYX_ALIGN_BLOCK:
2133                         case LYX_ALIGN_LAYOUT:
2134                         case LYX_ALIGN_SPECIAL: break;
2135                         case LYX_ALIGN_LEFT:
2136                                 file += "\\raggedright ";
2137                                 column+= 13;
2138                                 break;
2139                         case LYX_ALIGN_RIGHT:
2140                                 file += "\\raggedleft ";
2141                                 column+= 12;
2142                                 break;
2143                         case LYX_ALIGN_CENTER:
2144                                 file += "\\centering ";
2145                                 column+= 11;
2146                                 break;
2147                         }        
2148                 }
2149
2150                 int c = GetChar(i);
2151
2152                 // Fully instantiated font
2153                 LyXFont font = getFont(i);
2154                 last_font = running_font;
2155
2156                 // Spaces at end of font change are simulated to be
2157                 // outside font change, i.e. we write "\textXX{text} "
2158                 // rather than "\textXX{text }". (Asger)
2159                 if (open_font && c == ' ' && i <= size() - 2 
2160                     && !getFont(i+1).equalExceptLatex(running_font) 
2161                     && !getFont(i+1).equalExceptLatex(font)) {
2162                         font = getFont(i + 1);
2163                 }
2164                 // We end font definition before blanks
2165                 if (!font.equalExceptLatex(running_font) && open_font) {
2166                         column += running_font.latexWriteEndChanges(file,
2167                                                                     basefont,
2168                                                                     (i == main_body-1) ? basefont : font);
2169                         running_font = basefont;
2170                         open_font = false;
2171                 }
2172
2173                 // Blanks are printed before start of fontswitch
2174                 if (c == ' '){
2175                         // Do not print the separation of the optional argument
2176                         if (i != main_body - 1) {
2177                                 SimpleTeXBlanks(file, texrow, i,
2178                                                 column, font, style);
2179                         }
2180                 }
2181
2182                 // Do we need to change font?
2183                 if (!font.equalExceptLatex(running_font)
2184                     && i != main_body-1) {
2185                         column += font.latexWriteStartChanges(file, basefont, last_font);
2186                         running_font = font;
2187                         open_font = true;
2188                 }
2189
2190                 if (c == LyXParagraph::META_NEWLINE) {
2191                         // newlines are handled differently here than
2192                         // the default in SimpleTeXSpecialChars().
2193                         if (!style.newline_allowed
2194                             || font.latex() == LyXFont::ON) {
2195                                 file += '\n';
2196                         } else {
2197                                 if (open_font) {
2198                                         column += running_font.latexWriteEndChanges(file, basefont, basefont);
2199                                         open_font = false;
2200                                 }
2201                                 basefont = getFont(-1);
2202                                 running_font = basefont;
2203                                 if (font.family() == 
2204                                     LyXFont::TYPEWRITER_FAMILY) {
2205                                         file += "~";
2206                                 }
2207                                 file += "\\\\\n";
2208                         }
2209                         texrow.newline();
2210                         texrow.start(this, i + 1);
2211                         column = 0;
2212                 } else {
2213                         SimpleTeXSpecialChars(file, texrow,
2214                                               font, running_font, basefont,
2215                                               open_font, style, i, column, c);
2216                 }
2217         }
2218
2219         // If we have an open font definition, we have to close it
2220         if (open_font) {
2221                 running_font.latexWriteEndChanges(file, basefont, basefont);
2222         }
2223
2224         // Needed if there is an optional argument but no contents.
2225         if (main_body > 0 && main_body == size()) {
2226                 file += "]~";
2227                 return_value = false;
2228         }
2229
2230         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2231         return return_value;
2232 }
2233
2234
2235 // This one spits out the text of a table paragraph
2236 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2237 {
2238         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...     " << this << endl;
2239    
2240         bool return_value = false;
2241
2242         LyXLayout const & style = 
2243                 textclasslist.Style(current_view->buffer()->params.textclass,
2244                                     GetLayout());
2245  
2246         int column = 0;
2247         if (!IsDummy()) { // it is dummy if it is in a float!!!
2248                 if (style.isCommand()) {
2249                         file += '{';
2250                         ++column;
2251                 } else if (align != LYX_ALIGN_LAYOUT) {
2252                         file += '{';
2253                         ++column;
2254                         return_value = true;
2255                 }
2256                 if (noindent) {
2257                         file += "\\noindent ";
2258                         column += 10;
2259                 }
2260                 switch (align) {
2261                 case LYX_ALIGN_NONE:
2262                 case LYX_ALIGN_BLOCK:
2263                 case LYX_ALIGN_LAYOUT:
2264                 case LYX_ALIGN_SPECIAL: break;
2265                 case LYX_ALIGN_LEFT:
2266                         file += "\\raggedright ";
2267                         column+= 13;
2268                         break;
2269                 case LYX_ALIGN_RIGHT:
2270                         file += "\\raggedleft ";
2271                         column+= 12;
2272                         break;
2273                 case LYX_ALIGN_CENTER:
2274                         file += "\\centering ";
2275                         column+= 11;
2276                         break;
2277                 }
2278         }
2279
2280         LyXFont basefont = getFont(-1); // Get layout font
2281         // Which font is currently active?
2282         LyXFont running_font = basefont;
2283         LyXFont last_font;
2284         // Do we have an open font change?
2285         bool open_font = false;
2286         int current_cell_number = -1;
2287         int tmp = table->TexEndOfCell(file, current_cell_number);
2288         for (; tmp > 0 ; --tmp)
2289                 texrow.newline();
2290         
2291         texrow.start(this, 0);
2292
2293         for (size_type i = 0; i < size(); ++i) {
2294                 char c = GetChar(i);
2295                 if (table->IsContRow(current_cell_number + 1)) {
2296                         if (c == LyXParagraph::META_NEWLINE)
2297                                 ++current_cell_number;
2298                         continue;
2299                 }
2300                 ++column;
2301                 
2302                 // Fully instantiated font
2303                 LyXFont font = getFont(i);
2304                 last_font = running_font;
2305
2306                 // Spaces at end of font change are simulated to be
2307                 // outside font change.
2308                 // i.e. we write "\textXX{text} " rather than
2309                 // "\textXX{text }". (Asger)
2310                 if (open_font && c == ' ' && i <= size() - 2
2311                     && getFont(i+1) != running_font && getFont(i+1) != font) {
2312                         font = getFont(i+1);
2313                 }
2314
2315                 // We end font definition before blanks
2316                 if (font != running_font && open_font) {
2317                         column += running_font.latexWriteEndChanges(file,
2318                                                                     basefont, font);
2319                         running_font = basefont;
2320                         open_font = false;
2321                 }
2322                 // Blanks are printed before start of fontswitch
2323                 if (c == ' '){
2324                         SimpleTeXBlanks(file, texrow, i, column, font, style);
2325                 }
2326                 // Do we need to change font?
2327                 if (font != running_font) {
2328                         column += font.latexWriteStartChanges(file, basefont, last_font);
2329                         running_font = font;
2330                         open_font = true;
2331                 }
2332                 // Do we need to turn on LaTeX mode?
2333                 if (font.latex() != running_font.latex()) {
2334                         if (font.latex() == LyXFont::ON
2335                             && style.needprotect) {
2336                                 file += "\\protect ";
2337                                 column += 9;
2338                         }
2339                 }
2340                 if (c == LyXParagraph::META_NEWLINE) {
2341                         // special case for inside a table
2342                         // different from default case in
2343                         // SimpleTeXSpecialChars()
2344                         if (open_font) {
2345                                 column += running_font
2346                                         .latexWriteEndChanges(file, basefont, basefont);
2347                                 open_font = false;
2348                         }
2349                         basefont = getFont(-1);
2350                         running_font = basefont;
2351                         ++current_cell_number;
2352                         if (table->CellHasContRow(current_cell_number) >= 0) {
2353                                 TeXContTableRows(file, i + 1,
2354                                                  current_cell_number,
2355                                                  column, texrow);
2356                         }
2357                         // if this cell follow only ContRows till end don't
2358                         // put the EndOfCell because it is put after the
2359                         // for(...)
2360                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2361                                 --current_cell_number;
2362                                 break;
2363                         }
2364                         int tmp = table->TexEndOfCell(file,
2365                                                       current_cell_number);
2366                         if (tmp > 0) {
2367                                 column = 0;
2368                         } else if (tmp < 0) {
2369                                 tmp = -tmp;
2370                         }
2371                         for (; tmp--;) {
2372                                 texrow.newline();
2373                         }
2374                         texrow.start(this, i + 1);
2375                 } else {
2376                         SimpleTeXSpecialChars(file, texrow,
2377                                               font, running_font, basefont,
2378                                               open_font, style, i, column, c);
2379                 }
2380         }
2381
2382         // If we have an open font definition, we have to close it
2383         if (open_font) {
2384                 running_font.latexWriteEndChanges(file, basefont, basefont);
2385         }
2386         ++current_cell_number;
2387         tmp = table->TexEndOfCell(file, current_cell_number);
2388         for (; tmp > 0; --tmp)
2389                 texrow.newline();
2390         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2391         return return_value;
2392 }
2393
2394
2395 // This one spits out the text off ContRows in tables
2396 bool LyXParagraph::TeXContTableRows(string & file,
2397                                     LyXParagraph::size_type i,
2398                                     int current_cell_number,
2399                                     int & column, TexRow & texrow)
2400 {
2401         lyxerr[Debug::LATEX] << "TeXContTableRows...     " << this << endl;
2402         if (!table)
2403                 return false;
2404     
2405         char c;
2406    
2407         bool return_value = false;
2408         LyXLayout const & style =
2409                 textclasslist.Style(current_view->buffer()->params.textclass,
2410                                     GetLayout());
2411         LyXFont basefont = getFont(-1); // Get layout font
2412         LyXFont last_font;
2413         // Which font is currently active?
2414         LyXFont running_font = basefont;
2415         // Do we have an open font change?
2416         bool open_font = false;
2417
2418         size_type lastpos = i;
2419         int cell = table->CellHasContRow(current_cell_number);
2420         ++current_cell_number;
2421         while(cell >= 0) {
2422                 // first find the right position
2423                 i = lastpos;
2424                 for (; (i < size()) && (current_cell_number<cell); ++i) {
2425                         c = GetChar(i);
2426                         if (c == LyXParagraph::META_NEWLINE)
2427                                 ++current_cell_number;
2428                 }
2429                 lastpos = i;
2430                 c = GetChar(i);
2431                 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2432                         file += " \\\\\n";
2433                         texrow.newline();
2434                         column = 0;
2435                 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2436                         file += ' ';
2437                 }
2438
2439                 for (; i < size()
2440                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2441                      ++i) {
2442                         ++column;
2443
2444                         // Fully instantiated font
2445                         LyXFont font = getFont(i);
2446                         last_font = running_font;
2447
2448                         // Spaces at end of font change are simulated to
2449                         // be outside font change. i.e. we write
2450                         // "\textXX{text} " rather than "\textXX{text }".
2451                         // (Asger)
2452                         if (open_font && c == ' ' && i <= size() - 2 
2453                             && getFont(i + 1) != running_font
2454                             && getFont(i + 1) != font) {
2455                                 font = getFont(i + 1);
2456                         }
2457
2458                         // We end font definition before blanks
2459                         if (font != running_font && open_font) {
2460                                 column += running_font.latexWriteEndChanges(file, basefont, font);
2461                                 running_font = basefont;
2462                                 open_font = false;
2463                         }
2464                         // Blanks are printed before start of fontswitch
2465                         if (c == ' '){
2466                                 SimpleTeXBlanks(file, texrow, i,
2467                                                 column, font, style);
2468                         }
2469                         // Do we need to change font?
2470                         if (font != running_font) {
2471                                 column +=
2472                                         font.latexWriteStartChanges(file,
2473                                                                     basefont, last_font);
2474                                 running_font = font;
2475                                 open_font = true;
2476                         }
2477                         // Do we need to turn on LaTeX mode?
2478                         if (font.latex() != running_font.latex()) {
2479                                 if (font.latex() == LyXFont::ON
2480                                     && style.needprotect)
2481                                         {
2482                                                 file += "\\protect ";
2483                                                 column += 9;
2484                                         }
2485                         }
2486                         SimpleTeXSpecialChars(file, texrow, font,
2487                                               running_font, basefont,
2488                                               open_font, style, i, column, c);
2489                 }
2490                 // If we have an open font definition, we have to close it
2491                 if (open_font) {
2492                         running_font.latexWriteEndChanges(file, basefont, basefont);
2493                         open_font = false;
2494                 }
2495                 basefont = getFont(-1);
2496                 running_font = basefont;
2497                 cell = table->CellHasContRow(current_cell_number);
2498         }
2499         lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2500         return return_value;
2501 }
2502
2503
2504 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2505 {
2506         bool retval = false;
2507         switch (c) {
2508         case LyXParagraph::META_HFILL:
2509                 sgml_string.clear();
2510                 break;
2511 #if 0
2512         case LyXParagraph::META_PROTECTED_SEPARATOR: 
2513                 sgml_string = ' ';
2514                 break;
2515 #endif
2516         case LyXParagraph::META_NEWLINE:
2517                 sgml_string = '\n';
2518                 break;
2519         case '&': 
2520                 sgml_string = "&amp;";
2521                 break;
2522         case '<': 
2523                 sgml_string = "&lt;"; 
2524                 break;
2525         case '>':
2526                 sgml_string = "&gt;"; 
2527                 break;
2528         case '$': 
2529                 sgml_string = "&dollar;"; 
2530                 break;
2531         case '#': 
2532                 sgml_string = "&num;";
2533                 break;
2534         case '%': 
2535                 sgml_string = "&percnt;";
2536                 break;
2537         case '[': 
2538                 sgml_string = "&lsqb;";
2539                 break;
2540         case ']': 
2541                 sgml_string = "&rsqb;";
2542                 break;
2543         case '{': 
2544                 sgml_string = "&lcub;";
2545                 break;
2546         case '}': 
2547                 sgml_string = "&rcub;";
2548                 break;
2549         case '~': 
2550                 sgml_string = "&tilde;";
2551                 break;
2552         case '"': 
2553                 sgml_string = "&quot;";
2554                 break;
2555         case '\\': 
2556                 sgml_string = "&bsol;";
2557                 break;
2558         case ' ':
2559                 retval = true;
2560                 sgml_string = ' ';
2561                 break;
2562         case '\0': // Ignore :-)
2563                 sgml_string.clear();
2564                 break;
2565         default:
2566                 sgml_string = c;
2567                 break;
2568         }
2569         return retval;
2570 }
2571
2572
2573 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
2574                                             int & desc_on, int depth) 
2575 {
2576         if (!table) return;
2577         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2578         int column = 0;
2579         LyXFont font1, font2;
2580         char c;
2581         Inset * inset;
2582         size_type main_body;
2583         string emph = "emphasis";
2584         bool emph_flag = false;
2585         
2586         LyXLayout const & style =
2587                 textclasslist.Style(current_view->buffer()->params.textclass,
2588                                     GetLayout());
2589         
2590         if (style.labeltype != LABEL_MANUAL)
2591                 main_body = 0;
2592         else
2593                 main_body = BeginningOfMainBody();
2594         
2595         // Gets paragraph main font.
2596         if (main_body > 0)
2597                 font1 = style.labelfont;
2598         else
2599                 font1 = style.font;
2600         
2601         int char_line_count = depth;
2602         addNewlineAndDepth(file, depth);
2603         if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2604                 file += "<INFORMALTABLE>";
2605                 addNewlineAndDepth(file, ++depth);
2606         }
2607         int current_cell_number = -1;
2608         int tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2609         
2610         // Parsing main loop.
2611         for (size_type i = 0; i < size(); ++i) {
2612                 c = GetChar(i);
2613                 if (table->IsContRow(current_cell_number+1)) {
2614                         if (c == LyXParagraph::META_NEWLINE)
2615                                 ++current_cell_number;
2616                         continue;
2617                 }
2618                 ++column;
2619                 
2620                 // Fully instantiated font
2621                 font2 = getFont(i);
2622                 
2623                 // Handle <emphasis> tag.
2624                 if (font1.emph() != font2.emph() && i) {
2625                         if (font2.emph() == LyXFont::ON) {
2626                                 file += "<emphasis>";
2627                                 emph_flag= true;
2628                         } else if (emph_flag) {
2629                                 file += "</emphasis>";
2630                                 emph_flag= false;
2631                         }
2632                 }
2633                 if (c == LyXParagraph::META_NEWLINE) {
2634                         // We have only to control for emphasis open here!
2635                         if (emph_flag) {
2636                                 file += "</emphasis>";
2637                                 emph_flag= false;
2638                         }
2639                         font1 = font2 = getFont(-1);
2640                         ++current_cell_number;
2641                         if (table->CellHasContRow(current_cell_number) >= 0) {
2642                                 DocBookContTableRows(file, extra, desc_on, i+1,
2643                                                      current_cell_number,
2644                                                      column);
2645                         }
2646                         // if this cell follow only ContRows till end don't
2647                         // put the EndOfCell because it is put after the
2648                         // for(...)
2649                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2650                                 --current_cell_number;
2651                                 break;
2652                         }
2653                         tmp = table->DocBookEndOfCell(file,
2654                                                       current_cell_number,
2655                                                       depth);
2656                         
2657                         if (tmp > 0)
2658                                 column = 0;
2659                 } else if (c == LyXParagraph::META_INSET) {
2660                         inset = GetInset(i);
2661                         string tmp_out;
2662                         inset->DocBook(tmp_out);
2663                         //
2664                         // This code needs some explanation:
2665                         // Two insets are treated specially
2666                         //   label if it is the first element in a
2667                         //   command paragraph
2668                         //         desc_on == 3
2669                         //   graphics inside tables or figure floats
2670                         //   can't go on
2671                         //   title (the equivalente in latex for this
2672                         //   case is caption
2673                         //   and title should come first
2674                         //         desc_on == 4
2675                         //
2676                         if(desc_on != 3 || i != 0) {
2677                                 if(tmp_out[0] == '@') {
2678                                         if(desc_on == 4)
2679                                                 extra += frontStrip(tmp_out,
2680                                                                     '@');
2681                                         else
2682                                                 file += frontStrip(tmp_out,
2683                                                                    '@');
2684                                 } else
2685                                         file += tmp_out;
2686                         }
2687                 } else if (font2.latex() == LyXFont::ON) {
2688                         // "TeX"-Mode on == > SGML-Mode on.
2689                         if (c != '\0')
2690                                 file += c;
2691                         ++char_line_count;
2692                 } else {
2693                         string sgml_string;
2694                         if (linuxDocConvertChar(c, sgml_string) 
2695                             && !style.free_spacing) {
2696                                 // in freespacing mode, spaces are
2697                                 // non-breaking characters
2698                                 // char is ' '
2699                                 if (desc_on == 1) {
2700                                         ++char_line_count;
2701                                         file += '\n';
2702                                         file += "</term><listitem><para>";
2703                                         desc_on = 2;
2704                                 } else  {
2705                                         file += c;
2706                                 }
2707                         } else {
2708                                 file += sgml_string;
2709                         }
2710                 }
2711                 font1 = font2;
2712         }
2713         
2714         // Needed if there is an optional argument but no contents.
2715         if (main_body > 0 && main_body == size()) {
2716                 font1 = style.font;
2717         }
2718
2719         if (emph_flag) {
2720                 file += "</emphasis>";
2721         }
2722         
2723         ++current_cell_number;
2724         tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2725         // Resets description flag correctly.
2726         switch(desc_on){
2727         case 1:
2728                 // <term> not closed...
2729                 file += "</term>";
2730                 break;
2731         }
2732         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2733                 file += "</INFORMALTABLE>";
2734         file += '\n';
2735         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2736                              << this << endl;
2737 }
2738
2739
2740 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
2741                                         int & desc_on,
2742                                         LyXParagraph::size_type i,
2743                                         int current_cell_number, int &column) 
2744
2745 {
2746         if (!table) return;
2747         
2748         lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2749
2750         LyXFont font2;
2751         char c;
2752         Inset * inset;
2753         string emph= "emphasis";
2754         bool emph_flag= false;
2755         int char_line_count= 0;
2756         
2757         LyXLayout const & style =
2758                 textclasslist.Style(current_view->buffer()->params.textclass,
2759                                     GetLayout());
2760         
2761         size_type main_body;
2762         if (style.labeltype != LABEL_MANUAL)
2763                 main_body = 0;
2764         else
2765                 main_body = BeginningOfMainBody();
2766         
2767         // Gets paragraph main font.
2768         LyXFont font1;
2769         if (main_body > 0)
2770                 font1 = style.labelfont;
2771         else
2772                 font1 = style.font;
2773         
2774         size_type lastpos = i;
2775         int cell = table->CellHasContRow(current_cell_number);
2776         ++current_cell_number;
2777         while(cell >= 0) {
2778                 // first find the right position
2779                 i = lastpos;
2780                 for (; i < size() && current_cell_number < cell; ++i) {
2781                         c = GetChar(i);
2782                         if (c == LyXParagraph::META_NEWLINE)
2783                                 ++current_cell_number;
2784                 }
2785                 lastpos = i;
2786                 c = GetChar(i);
2787                 // I don't know how to handle this so I comment it
2788                 // for the moment (Jug)
2789 //             if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2790 //                     file += " \\\\\n";
2791 //                     column = 0;
2792 //             } else
2793                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2794                         file += ' ';
2795                 }
2796
2797                 for (; i < size()
2798                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2799                      ++i) {
2800                         ++column;
2801                         
2802                         // Fully instantiated font
2803                         font2 = getFont(i);
2804                         
2805                         // Handle <emphasis> tag.
2806                         if (font1.emph() != font2.emph() && i) {
2807                                 if (font2.emph() == LyXFont::ON) {
2808                                         file += "<emphasis>";
2809                                         emph_flag= true;
2810                                 } else if (emph_flag) {
2811                                         file += "</emphasis>";
2812                                         emph_flag= false;
2813                                 }
2814                         }
2815                         if (c == LyXParagraph::META_INSET) {
2816                                 inset = GetInset(i);
2817                                 string tmp_out;
2818                                 inset->DocBook(tmp_out);
2819                                 //
2820                                 // This code needs some explanation:
2821                                 // Two insets are treated specially
2822                                 //   label if it is the first element in a
2823                                 //   command paragraph
2824                                 //       desc_on == 3
2825                                 //   graphics inside tables or figure floats
2826                                 //   can't go on title (the equivalente in
2827                                 //   latex for this case is caption and title
2828                                 //   should come first
2829                                 //       desc_on == 4
2830                                 //
2831                                 if(desc_on != 3 || i != 0) {
2832                                         if(tmp_out[0] == '@') {
2833                                                 if(desc_on == 4)
2834                                                         extra += frontStrip(tmp_out, '@');
2835                                                 else
2836                                                         file += frontStrip(tmp_out, '@');
2837                                         } else
2838                                                 file += tmp_out;
2839                                 }
2840                         } else if (font2.latex() == LyXFont::ON) {
2841                                 // "TeX"-Mode on == > SGML-Mode on.
2842                                 if (c!= '\0')
2843                                         file += c;
2844                                 ++char_line_count;
2845                         } else {
2846                                 string sgml_string;
2847                                 if (linuxDocConvertChar(c, sgml_string) 
2848                                     && !style.free_spacing) {
2849                                         // in freespacing mode, spaces are
2850                                         // non-breaking characters
2851                                         // char is ' '
2852                                         if (desc_on == 1) {
2853                                                 ++char_line_count;
2854                                                 file += '\n';
2855                                                 file += "</term><listitem><para>";
2856                                                 desc_on = 2;
2857                                         } else  {
2858                                                 file += c;
2859                                         }
2860                                 } else {
2861                                         file += sgml_string;
2862                                 }
2863                         }
2864                 }
2865                 // we have only to control for emphasis open here!
2866                 if (emph_flag) {
2867                         file += "</emphasis>";
2868                         emph_flag= false;
2869                 }
2870                 font1 = font2 = getFont(-1);
2871                 cell = table->CellHasContRow(current_cell_number);
2872         }
2873         lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
2874 }
2875
2876
2877 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
2878                                    LyXParagraph::size_type const i,
2879                                    int & column, LyXFont const & font,
2880                                    LyXLayout const & style)
2881 {
2882         if (column > tex_code_break_column
2883             && i 
2884             && GetChar(i - 1) != ' '
2885             && (i < size() - 1)
2886             // In LaTeX mode, we don't want to
2887             // break lines since some commands
2888             // do not like this
2889             && ! (font.latex() == LyXFont::ON)
2890             // same in FreeSpacing mode
2891             && !style.free_spacing
2892             // In typewriter mode, we want to avoid 
2893             // ! . ? : at the end of a line
2894             && !(font.family() == LyXFont::TYPEWRITER_FAMILY
2895                  && (GetChar(i-1) == '.'
2896                      || GetChar(i-1) == '?' 
2897                      || GetChar(i-1) == ':'
2898                      || GetChar(i-1) == '!'))) {
2899                 if (tex_code_break_column == 0) {
2900                         // in batchmode we need LaTeX to still
2901                         // see it as a space not as an extra '\n'
2902                         file += " %\n";
2903                 } else {
2904                         file += '\n';
2905                 }
2906                 texrow.newline();
2907                 texrow.start(this, i+1);
2908                 column = 0;
2909         } else if (font.latex() == LyXFont::OFF) {
2910                 if (style.free_spacing) {
2911                         file += '~';
2912                 } else {
2913                         file += ' ';
2914                 }
2915         }
2916 }
2917
2918
2919 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
2920                                          LyXFont & font,
2921                                          LyXFont & running_font,
2922                                          LyXFont & basefont,
2923                                          bool & open_font,
2924                                          LyXLayout const & style,
2925                                          LyXParagraph::size_type & i,
2926                                          int & column, char const c)
2927 {
2928         // Two major modes:  LaTeX or plain
2929         // Handle here those cases common to both modes
2930         // and then split to handle the two modes separately.
2931         switch (c) {
2932         case LyXParagraph::META_INSET: {
2933                 Inset * inset = GetInset(i);
2934                 if (inset) {
2935                         bool close = false;
2936                         int len = file.length();
2937                         if ((inset->LyxCode() == Inset::GRAPHICS_CODE
2938                              || inset->LyxCode() == Inset::MATH_CODE
2939                              || inset->LyxCode() == Inset::URL_CODE)
2940                             && running_font.getFontDirection()
2941                             == LYX_DIR_RIGHT_TO_LEFT) {
2942                                 file += "\\L{";
2943                                 close = true;
2944                         }
2945                         int tmp = inset->Latex(file, style.isCommand());
2946                         if (close)
2947                                 file += "}";
2948                         
2949                         if (tmp) {
2950                                 column = 0;
2951                         } else {
2952                                 column += file.length() - len;
2953                         }
2954                         for (; tmp--;) {
2955                                 texrow.newline();
2956                         }
2957                 }
2958         }
2959         break;
2960
2961         case LyXParagraph::META_NEWLINE:
2962                 if (open_font) {
2963                         column += running_font.latexWriteEndChanges(file,
2964                                                                     basefont, basefont);
2965                         open_font = false;
2966                 }
2967                 basefont = getFont(-1);
2968                 running_font = basefont;
2969                 break;
2970
2971         case LyXParagraph::META_HFILL: 
2972                 file += "\\hfill{}";
2973                 column += 7;
2974                 break;
2975
2976         default:
2977                 // And now for the special cases within each mode
2978                 // Are we in LaTeX mode?
2979                 if (font.latex() == LyXFont::ON) {
2980                         // at present we only have one option
2981                         // but I'll leave it as a switch statement
2982                         // so its simpler to extend. (ARRae)
2983                         switch (c) {
2984 #if 0
2985                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
2986                                 file += ' ';
2987                                 break;
2988 #endif
2989                         default:
2990                                 // make sure that we will not print
2991                                 // error generating chars to the tex
2992                                 // file. This test would not be needed
2993                                 // if it were done in the buffer
2994                                 // itself.
2995                                 if (c != '\0') {
2996                                         file += c;
2997                                 }
2998                                 break;
2999                         }
3000                 } else {
3001                         // Plain mode (i.e. not LaTeX)
3002                         switch (c) {
3003 #if 0
3004                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
3005                                 file += '~';
3006                                 break;
3007 #endif
3008                         case '\\': 
3009                                 file += "\\textbackslash{}";
3010                                 column += 15;
3011                                 break;
3012                 
3013                         case '°': case '±': case '²': case '³':  
3014                         case '×': case '÷': case '¹': case 'ª':
3015                         case 'º': case '¬': case 'µ':
3016                                 if (current_view->buffer()->params.inputenc == "latin1") {
3017                                         file += "\\ensuremath{";
3018                                         file += c;
3019                                         file += '}';
3020                                         column += 13;
3021                                 } else {
3022                                         file += c;
3023                                 }
3024                                 break;
3025
3026                         case '|': case '<': case '>':
3027                                 // In T1 encoding, these characters exist
3028                                 if (lyxrc->fontenc == "T1") {
3029                                         file += c;
3030                                         //... but we should avoid ligatures
3031                                         if ((c == '>' || c == '<')
3032                                             && i <= size() - 2
3033                                             && GetChar(i+1) == c){
3034                                                 file += "\\textcompwordmark{}";
3035                                                 column += 19;
3036                                         }
3037                                         break;
3038                                 }
3039                                 // Typewriter font also has them
3040                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3041                                         file += c;
3042                                         break;
3043                                 } 
3044                                 // Otherwise, we use what LaTeX
3045                                 // provides us.
3046                                 switch(c) {
3047                                 case '<':
3048                                         file += "\\textless{}";
3049                                         column += 10;
3050                                         break;
3051                                 case '>':
3052                                         file += "\\textgreater{}";
3053                                         column += 13;
3054                                         break;
3055                                 case '|':
3056                                         file += "\\textbar{}";
3057                                         column += 9;
3058                                         break;
3059                                 }
3060                                 break;
3061
3062                         case '-': // "--" in Typewriter mode -> "-{}-"
3063                                 if (i <= size() - 2
3064                                     && GetChar(i + 1) == '-'
3065                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3066                                         file += "-{}";
3067                                         column += 2;
3068                                 } else {
3069                                         file += '-';
3070                                 }
3071                                 break;
3072
3073                         case '\"': 
3074                                 file += "\\char`\\\"{}";
3075                                 column += 9;
3076                                 break;
3077
3078                         case '£':
3079                                 if (current_view->buffer()->params.inputenc == "default") {
3080                                         file += "\\pounds{}";
3081                                         column += 8;
3082                                 } else {
3083                                         file += c;
3084                                 }
3085                                 break;
3086
3087                         case '$': case '&':
3088                         case '%': case '#': case '{':
3089                         case '}': case '_':
3090                                 file += '\\';
3091                                 file += c;
3092                                 column += 1;
3093                                 break;
3094
3095                         case '~':
3096                                 file += "\\textasciitilde{}";
3097                                 column += 16;
3098                                 break;
3099
3100                         case '^':
3101                                 file += "\\textasciicircum{}";
3102                                 column += 17;
3103                                 break;
3104
3105                         case '*': case '[': case ']':
3106                                 // avoid being mistaken for optional arguments
3107                                 file += '{';
3108                                 file += c;
3109                                 file += '}';
3110                                 column += 2;
3111                                 break;
3112
3113                         case ' ':
3114                                 // Blanks are printed before font switching.
3115                                 // Sure? I am not! (try nice-latex)
3116                                 // I am sure it's correct. LyX might be smarter
3117                                 // in the future, but for now, nothing wrong is
3118                                 // written. (Asger)
3119                                 break;
3120
3121                         default:
3122                                 /* idea for labels --- begin*/
3123                                 // Check for "LyX"
3124                                 if (c ==  'L'
3125                                     && i <= size() - 3
3126                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
3127                                     && GetChar(i + 1) == 'y'
3128                                     && GetChar(i + 2) == 'X') {
3129                                         file += "\\LyX{}";
3130                                         i += 2;
3131                                         column += 5;
3132                                 }
3133                                 // Check for "TeX"
3134                                 else if (c == 'T'
3135                                          && i <= size() - 3
3136                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3137                                          && GetChar(i + 1) == 'e'
3138                                          && GetChar(i + 2) == 'X') {
3139                                         file += "\\TeX{}";
3140                                         i += 2;
3141                                         column += 5;
3142                                 }
3143                                 // Check for "LaTeX2e"
3144                                 else if (c == 'L'
3145                                          && i <= size() - 7
3146                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3147                                          && GetChar(i + 1) == 'a'
3148                                          && GetChar(i + 2) == 'T'
3149                                          && GetChar(i + 3) == 'e'
3150                                          && GetChar(i + 4) == 'X'
3151                                          && GetChar(i + 5) == '2'
3152                                          && GetChar(i + 6) == 'e') {
3153                                         file += "\\LaTeXe{}";
3154                                         i += 6;
3155                                         column += 8;
3156                                 }
3157                                 // Check for "LaTeX"
3158                                 else if (c == 'L'
3159                                          && i <= size() - 5
3160                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3161                                          && GetChar(i + 1) == 'a'
3162                                          && GetChar(i + 2) == 'T'
3163                                          && GetChar(i + 3) == 'e'
3164                                          && GetChar(i + 4) == 'X') {
3165                                         file += "\\LaTeX{}";
3166                                         i += 4;
3167                                         column += 7;
3168                                         /* idea for labels --- end*/ 
3169                                 } else if (c != '\0') {
3170                                         file += c;
3171                                 }
3172                                 break;
3173                         }
3174                 }
3175         }
3176 }
3177
3178
3179 #if 0
3180 bool LyXParagraph::RoffContTableRows(ostream & os,
3181                                      LyXParagraph::size_type i,
3182                                      int actcell)
3183 {
3184         if (!table)
3185                 return false;
3186
3187         LyXFont font1(LyXFont::ALL_INHERIT);
3188         LyXFont font2;
3189         Inset * inset;
3190         char c;
3191
3192         string fname2 = TmpFileName(string(), "RAT2");
3193         int lastpos = i;
3194         int cell = table->CellHasContRow(actcell);
3195         ++actcell;
3196         while(cell >= 0) {
3197                 // first find the right position
3198                 i = lastpos;
3199                 for (; i < size() && actcell < cell; ++i) {
3200                         c = GetChar(i);
3201                         if (c == LyXParagraph::META_NEWLINE)
3202                                 ++actcell;
3203                 }
3204                 lastpos = i;
3205                 c = GetChar(i);
3206                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3207                         os << " ";
3208                 for (; i < size()
3209                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3210                      ++i) {
3211                         font2 = GetFontSettings(i);
3212                         if (font1.latex() != font2.latex()) {
3213                                 if (font2.latex() != LyXFont::OFF)
3214                                         continue;
3215                         }
3216                         c = GetChar(i);
3217                         switch (c) {
3218                         case LyXParagraph::META_INSET:
3219                                 if ((inset = GetInset(i))) {
3220 #if 1
3221 #ifdef HAVE_SSTREAM
3222                                         stringstream ss(ios::in | ios::out);
3223                                         inset->Latex(ss, -1);
3224                                         ss.seekp(0);
3225                                         ss.get(c);
3226                                         while (!ss) {
3227                                                 if (c == '\\')
3228                                                         os << "\\\\";
3229                                                 else
3230                                                         os << c;
3231                                                 ss.get(c);
3232                                         }
3233 #else
3234                                         strstream ss;
3235                                         inset->Latex(ss, -1);
3236                                         ss.seekp(0);
3237                                         ss.get(c);
3238                                         while (!ss) {
3239                                                 if (c == '\\')
3240                                                         os << "\\\\";
3241                                                 else
3242                                                         os << c;
3243                                                 ss.get(c);
3244                                         }
3245                                         delete [] ss.str();
3246 #endif
3247 #else
3248                                         fstream fs(fname2.c_str(),
3249                                                    ios::in|ios::out);
3250                                         if (!fs) {
3251                                                 WriteAlert(_("LYX_ERROR:"),
3252                                                            _("Cannot open temporary file:"),
3253                                                            fname2);
3254                                                 return false;
3255                                         }
3256                                         inset->Latex(fs, -1);
3257                                         fs.seekp(0);
3258                                         fs.get(c);
3259                                         while (!fs) {
3260                                                 if (c == '\\')
3261                                                         os << "\\\\";
3262                                                 else
3263                                                         os << c;
3264                                                 fs.get(c);
3265                                         }
3266                                         fs.close();
3267 #endif
3268                                 }
3269                                 break;
3270                         case LyXParagraph::META_NEWLINE:
3271                                 break;
3272                         case LyXParagraph::META_HFILL: 
3273                                 break;
3274 #if 0
3275                         case LyXParagraph::META_PROTECTED_SEPARATOR:
3276                                 break;
3277 #endif
3278                         case '\\': 
3279                                 os << "\\\\";
3280                                 break;
3281                         default:
3282                                 if (c != '\0')
3283                                         os << c;
3284                                 else
3285                                         lyxerr.debug() << "RoffAsciiTable: "
3286                                                 "NULL char in structure."
3287                                                        << endl;
3288                                 break;
3289                         }
3290                 }
3291                 cell = table->CellHasContRow(actcell);
3292         }
3293         return true;
3294 }
3295 #endif
3296
3297
3298 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
3299                                        string & foot, TexRow & foot_texrow,
3300                                        int & foot_count)
3301 {
3302         lyxerr[Debug::LATEX] << "TeXDeeper...     " << this << endl;
3303         LyXParagraph * par = this;
3304
3305         while (par && par->depth == depth) {
3306                 if (par->IsDummy())
3307                         lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3308                 if (textclasslist.Style(current_view->buffer()->params.textclass, 
3309                                         par->layout).isEnvironment()
3310                     || par->pextra_type != PEXTRA_NONE) 
3311                         {
3312                                 par = par->TeXEnvironment(file, texrow,
3313                                                           foot, foot_texrow,
3314                                                           foot_count);
3315                         } else {
3316                                 par = par->TeXOnePar(file, texrow,
3317                                                      foot, foot_texrow,
3318                                                      foot_count);
3319                         }
3320         }
3321         lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3322
3323         return par;
3324 }
3325
3326
3327 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
3328                                             string & foot,
3329                                             TexRow & foot_texrow,
3330                                             int & foot_count)
3331 {
3332         bool eindent_open = false;
3333         bool foot_this_level = false;
3334         // flags when footnotetext should be appended to file.
3335         static bool minipage_open = false;
3336         static int minipage_open_depth = 0;
3337         char par_sep = current_view->buffer()->params.paragraph_separation;
3338     
3339         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << this << endl;
3340         if (IsDummy())
3341                 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3342
3343         LyXLayout const & style =
3344                 textclasslist.Style(current_view->buffer()->params.textclass,
3345                                     layout);
3346        
3347         if (pextra_type == PEXTRA_INDENT) {
3348                 if (!pextra_width.empty()) {
3349                         file += "\\begin{LyXParagraphIndent}{"
3350                                 + pextra_width + "}\n";
3351                 } else {
3352                         //float ib = atof(pextra_widthp.c_str())/100;
3353                         // string can't handle floats at present (971109)
3354                         // so I'll do a conversion by hand knowing that
3355                         // the limits are 0.0 to 1.0. ARRae.
3356                         file += "\\begin{LyXParagraphIndent}{";
3357                         switch (pextra_widthp.length()) {
3358                         case 3:
3359                                 file += "1.00";
3360                                 break;
3361                         case 2:
3362                                 file += "0.";
3363                                 file += pextra_widthp;
3364                                 break;
3365                         case 1:
3366                                 file += "0.0";
3367                                 file += pextra_widthp;
3368                         }
3369                         file += "\\columnwidth}\n";
3370                 }
3371                 texrow.newline();
3372                 eindent_open = true;
3373         }
3374         if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3375                 if (pextra_hfill && Previous() &&
3376                     (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3377                         file += "\\hfill{}\n";
3378                         texrow.newline();
3379                 }
3380                 if (par_sep == BufferParams::PARSEP_INDENT) {
3381                         file += "{\\setlength\\parindent{0pt}\n";
3382                         texrow.newline();
3383                 }
3384                 file += "\\begin{minipage}";
3385                 switch(pextra_alignment) {
3386                 case MINIPAGE_ALIGN_TOP:
3387                         file += "[t]";
3388                         break;
3389                 case MINIPAGE_ALIGN_MIDDLE:
3390                         file += "[m]";
3391                         break;
3392                 case MINIPAGE_ALIGN_BOTTOM:
3393                         file += "[b]";
3394                         break;
3395                 }
3396                 if (!pextra_width.empty()) {
3397                         file += '{';
3398                         file += pextra_width + "}\n";
3399                 } else {
3400                         //float ib = atof(par->pextra_width.c_str())/100;
3401                         // string can't handle floats at present
3402                         // so I'll do a conversion by hand knowing that
3403                         // the limits are 0.0 to 1.0. ARRae.
3404                         file += '{';
3405                         switch (pextra_widthp.length()) {
3406                         case 3:
3407                                 file += "1.00";
3408                                 break;
3409                         case 2:
3410                                 file += "0.";
3411                                 file += pextra_widthp;
3412                                 break;
3413                         case 1:
3414                                 file += "0.0";
3415                                 file += pextra_widthp;
3416                         }
3417                         file += "\\columnwidth}\n";
3418                 }
3419                 texrow.newline();
3420                 if (par_sep == BufferParams::PARSEP_INDENT) {
3421                         file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3422                         texrow.newline();
3423                 }
3424                 minipage_open = true;
3425                 minipage_open_depth = depth;
3426         }
3427
3428 #ifdef WITH_WARNINGS
3429 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3430         //I disabled it because it breaks when lists span on several
3431         //pages (JMarc)
3432 #endif
3433         if (style.isEnvironment()){
3434                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3435 #ifdef FANCY_FOOTNOTE_CODE
3436                         if (foot_count < 0) {
3437                                 // flag that footnote[mark][text] should be
3438                                 // used for any footnotes from now on
3439                                 foot_count = 0;
3440                                 foot_this_level = true;
3441                         }
3442 #endif
3443                         file += "\\begin{" + style.latexname() + "}{"
3444                                 + labelwidthstring + "}\n";
3445                 } else if (style.labeltype == LABEL_BIBLIO) {
3446                         // ale970405
3447                         file += "\\begin{" + style.latexname() + "}{"
3448                                 + bibitemWidthest(current_view->painter())
3449                                 + "}\n";
3450                 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3451 #ifdef FANCY_FOOTNOTE_CODE
3452                         if (foot_count < 0) {
3453                                 // flag that footnote[mark][text] should be
3454                                 // used for any footnotes from now on
3455                                 foot_count = 0;
3456                                 foot_this_level = true;
3457                         }
3458 #endif
3459                         file += "\\begin{" + style.latexname() + '}'
3460                                 + style.latexparam() + '\n';
3461                 } else 
3462                         file += "\\begin{" + style.latexname() + '}'
3463                                 + style.latexparam() + '\n';
3464                 texrow.newline();
3465         }
3466         LyXParagraph * par = this;
3467         do {
3468                 par = par->TeXOnePar(file, texrow,
3469                                      foot, foot_texrow, foot_count);
3470
3471                 if (minipage_open && par && !style.isEnvironment() &&
3472                     (par->pextra_type == PEXTRA_MINIPAGE) &&
3473                     par->pextra_start_minipage) {
3474                         file += "\\end{minipage}\n";
3475                         texrow.newline();
3476                         if (par_sep == BufferParams::PARSEP_INDENT) {
3477                                 file += "}\n";
3478                                 texrow.newline();
3479                         }
3480                         minipage_open = false;
3481                 }
3482                 if (par && par->depth > depth) {
3483                         if (textclasslist.Style(current_view->buffer()->params.textclass,
3484                                                 par->layout).isParagraph()
3485                             && !par->table
3486                             && !suffixIs(file, "\n\n")) {
3487                                 // There should be at least one '\n' already
3488                                 // but we need there to be two for Standard 
3489                                 // paragraphs that are depth-increment'ed to be
3490                                 // output correctly.  However, tables can
3491                                 // also be paragraphs so don't adjust them.
3492                                 // ARRae
3493                                 file += '\n';
3494                                 texrow.newline();
3495                         }
3496                         par = par->TeXDeeper(file, texrow,
3497                                              foot, foot_texrow, foot_count);
3498                 }
3499                 if (par && par->layout == layout && par->depth == depth &&
3500                     (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3501                         if (par->pextra_hfill && par->Previous() &&
3502                             (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3503                                 file += "\\hfill{}\n";
3504                                 texrow.newline();
3505                         }
3506                         if (par_sep == BufferParams::PARSEP_INDENT) {
3507                                 file += "{\\setlength\\parindent{0pt}\n";
3508                                 texrow.newline();
3509                         }
3510                         file += "\\begin{minipage}";
3511                         switch(par->pextra_alignment) {
3512                         case MINIPAGE_ALIGN_TOP:
3513                                 file += "[t]";
3514                                 break;
3515                         case MINIPAGE_ALIGN_MIDDLE:
3516                                 file += "[m]";
3517                                 break;
3518                         case MINIPAGE_ALIGN_BOTTOM:
3519                                 file += "[b]";
3520                                 break;
3521                         }
3522                         if (!par->pextra_width.empty()) {
3523                                 file += '{';
3524                                 file += par->pextra_width;
3525                                 file += "}\n";
3526                         } else {
3527                                 //float ib = atof(par->pextra_widthp.c_str())/100;
3528                                 // string can't handle floats at present
3529                                 // so I'll do a conversion by hand knowing that
3530                                 // the limits are 0.0 to 1.0. ARRae.
3531                                 file += '{';
3532                                 switch (par->pextra_widthp.length()) {
3533                                 case 3:
3534                                         file += "1.00";
3535                                         break;
3536                                 case 2:
3537                                         file += "0.";
3538                                         file += par->pextra_widthp;
3539                                         break;
3540                                 case 1:
3541                                         file += "0.0";
3542                                         file += par->pextra_widthp;
3543                                 }
3544                                 file += "\\columnwidth}\n";
3545                         }
3546                         texrow.newline();
3547                         if (par_sep == BufferParams::PARSEP_INDENT) {
3548                                 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3549                                 texrow.newline();
3550                         }
3551                         minipage_open = true;
3552                         minipage_open_depth = par->depth;
3553                 }
3554         } while (par
3555                  && par->layout == layout
3556                  && par->depth == depth
3557                  && par->pextra_type == pextra_type);
3558  
3559         if (style.isEnvironment()) {
3560                 file += "\\end{" + style.latexname() + '}';
3561                 // maybe this should go after the minipage closes?
3562                 if (foot_this_level) {
3563                         if (foot_count >= 1) {
3564                                 if (foot_count > 1) {
3565                                         file += "\\addtocounter{footnote}{-";
3566                                         file += tostr(foot_count - 1);
3567                                         file += '}';
3568                                 }
3569                                 file += foot;
3570                                 texrow += foot_texrow;
3571                                 foot.clear();
3572                                 foot_texrow.reset();
3573                                 foot_count = 0;
3574                         }
3575                 }
3576         }
3577         if (minipage_open && (minipage_open_depth == depth) &&
3578             (!par || par->pextra_start_minipage ||
3579              par->pextra_type != PEXTRA_MINIPAGE)) {
3580                 file += "\\end{minipage}\n";
3581                 texrow.newline();
3582                 if (par_sep == BufferParams::PARSEP_INDENT) {
3583                         file += "}\n";
3584                         texrow.newline();
3585                 }
3586                 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3587                         file += "\\medskip\n\n";
3588                         texrow.newline();
3589                         texrow.newline();
3590                 }
3591                 minipage_open = false;
3592         }
3593         if (eindent_open) {
3594                 file += "\\end{LyXParagraphIndent}\n";
3595                 texrow.newline();
3596         }
3597         if (!(par && (par->pextra_type == PEXTRA_MINIPAGE) 
3598               && par->pextra_hfill)) {
3599                 file += '\n';
3600                 texrow.newline();
3601         }
3602         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3603         return par;  // ale970302
3604 }
3605
3606
3607 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
3608                                          string & foot, TexRow & foot_texrow,
3609                                          int & foot_count,
3610                                          LyXDirection par_direction)
3611 {
3612         lyxerr[Debug::LATEX] << "TeXFootnote...  " << this << endl;
3613         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3614                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3615                         "No footnote!" << endl;
3616
3617         LyXParagraph * par = this;
3618         LyXLayout const & style =
3619                 textclasslist.Style(current_view->buffer()->params.textclass, 
3620                                     previous->GetLayout());
3621         
3622         if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3623                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3624                         "Float other than footnote in command"
3625                         " with moving argument is illegal" << endl;
3626         }
3627
3628         if (footnotekind != LyXParagraph::FOOTNOTE
3629             && footnotekind != LyXParagraph::MARGIN
3630             && file.length()
3631             && !suffixIs(file, '\n')) {
3632                 // we need to ensure that real floats like tables and figures
3633                 // have their \begin{} on a new line otherwise we can get
3634                 // incorrect results when using the endfloat.sty package
3635                 // especially if two floats follow one another.  ARRae 981022
3636                 // NOTE: if the file is length 0 it must have just been
3637                 //       written out so we assume it ended with a '\n'
3638                 file += '\n';
3639                 texrow.newline();
3640         }
3641         
3642         BufferParams * params = &current_view->buffer()->params;
3643         bool footer_in_body = true;
3644         switch (footnotekind) {
3645         case LyXParagraph::FOOTNOTE:
3646                 if (style.intitle) {
3647                         file += "\\thanks{\n";
3648                         footer_in_body = false;
3649                 } else {
3650                         if (foot_count == -1) {
3651                                 // we're at depth 0 so we can use:
3652                                 file += "\\footnote{%\n";
3653                                 footer_in_body = false;
3654                         } else {
3655                                 file += "\\footnotemark{}%\n";
3656                                 if (foot_count) {
3657                                         // we only need this when there are
3658                                         // multiple footnotes
3659                                         foot += "\\stepcounter{footnote}";
3660                                 }
3661                                 foot += "\\footnotetext{%\n";
3662                                 foot_texrow.start(this, 0);
3663                                 foot_texrow.newline();
3664                                 ++foot_count;
3665                         }
3666                 }
3667                 break;
3668         case LyXParagraph::MARGIN:
3669                 file += "\\marginpar{\n";
3670                 break;
3671         case LyXParagraph::FIG:
3672                 if (pextra_type == PEXTRA_FLOATFLT
3673                     && (!pextra_width.empty()
3674                         || !pextra_widthp.empty())) {
3675                         char bufr[80];
3676                         if (!pextra_width.empty())
3677                                 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
3678                                         pextra_width.c_str());
3679                         else
3680                                 sprintf(bufr,
3681                                         "\\begin{floatingfigure}{%f\\textwidth}\n",
3682                                         atoi(pextra_widthp.c_str())/100.0);
3683                         file += bufr;
3684                 } else {
3685                         file += "\\begin{figure}";
3686                         if (!params->float_placement.empty()) { 
3687                                 file += '[';
3688                                 file += params->float_placement;
3689                                 file += "]\n";
3690                         } else {
3691                                 file += '\n';
3692                         }
3693                 }
3694                 break;
3695         case LyXParagraph::TAB:
3696                 file += "\\begin{table}";
3697                 if (!params->float_placement.empty()) { 
3698                         file += '[';
3699                         file += params->float_placement;
3700                         file += "]\n";
3701                 } else {
3702                         file += '\n';
3703                 }
3704                 break;
3705         case LyXParagraph::WIDE_FIG:
3706                 file += "\\begin{figure*}";
3707                 if (!params->float_placement.empty()) { 
3708                         file += '[';
3709                         file += params->float_placement;
3710                         file += "]\n";
3711                 } else {
3712                         file += '\n';
3713                 }
3714                 break;
3715         case LyXParagraph::WIDE_TAB:
3716                 file += "\\begin{table*}";
3717                 if (!params->float_placement.empty()) { 
3718                         file += '[';
3719                         file += params->float_placement;
3720                         file += "]\n";
3721                 } else {
3722                         file += '\n';
3723                 }
3724                 break;
3725         case LyXParagraph::ALGORITHM:
3726                 file += "\\begin{algorithm}\n";
3727                 break;
3728         }
3729         texrow.newline();
3730    
3731  
3732         LyXDirection direction = getParDirection();
3733         if (direction != par_direction) {
3734                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
3735                         file += "\\unsethebrew\n";
3736                 else
3737                         file += "\\sethebrew\n";
3738                 texrow.newline();
3739         }
3740
3741         if (footnotekind != LyXParagraph::FOOTNOTE
3742             || !footer_in_body) {
3743                 // Process text for all floats except footnotes in body
3744                 do {
3745                         LyXLayout const & style =
3746                                 textclasslist
3747                                 .Style(current_view->buffer()->params
3748                                        .textclass,
3749                                        par->layout);
3750                         if (par->IsDummy())
3751                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3752                                        << endl;
3753                         if (style.isEnvironment()
3754                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3755                                 // Allows the use of minipages within float
3756                                 // environments. Shouldn't be circular because
3757                                 // we don't support footnotes inside
3758                                 // floats (yet). ARRae
3759                                 par = par->TeXEnvironment(file, texrow,
3760                                                           foot, foot_texrow,
3761                                                           foot_count);
3762                         } else {
3763                                 par = par->TeXOnePar(file, texrow,
3764                                                      foot, foot_texrow,
3765                                                      foot_count);
3766                         }
3767                         
3768                         if (par && !par->IsDummy() && par->depth > depth) {
3769                                 par = par->TeXDeeper(file, texrow,
3770                                                      foot, foot_texrow,
3771                                                      foot_count);
3772                         }
3773                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3774         } else {
3775                 // process footnotes > depth 0 or in environments separately
3776                 // NOTE: Currently don't support footnotes within footnotes
3777                 //       even though that is possible using the \footnotemark
3778                 string dummy;
3779                 TexRow dummy_texrow;
3780                 int dummy_count = 0;
3781                 do {
3782                         LyXLayout const & style =
3783                                 textclasslist
3784                                 .Style(current_view->buffer()->params
3785                                        .textclass,
3786                                        par->layout);
3787                         if (par->IsDummy())
3788                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3789                                        << endl;
3790                         if (style.isEnvironment()
3791                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3792                                 // Allows the use of minipages within float
3793                                 // environments. Shouldn't be circular because
3794                                 // we don't support footnotes inside
3795                                 // floats (yet). ARRae
3796                                 par = par->TeXEnvironment(foot, foot_texrow,
3797                                                           dummy, dummy_texrow,
3798                                                           dummy_count);
3799                         } else {
3800                                 par = par->TeXOnePar(foot, foot_texrow,
3801                                                      dummy, dummy_texrow,
3802                                                      dummy_count);
3803                         }
3804
3805                         if (par && !par->IsDummy() && par->depth > depth) {
3806                                 par = par->TeXDeeper(foot, foot_texrow,
3807                                                      dummy, dummy_texrow,
3808                                                      dummy_count);
3809                         }
3810                 } while (par
3811                          && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3812                 if (dummy_count) {
3813                         lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3814                                 "Footnote in a Footnote -- not supported"
3815                                << endl;
3816                 }
3817         }
3818
3819         switch (footnotekind) {
3820         case LyXParagraph::FOOTNOTE:
3821                 if (footer_in_body) {
3822                         // This helps tell which of the multiple
3823                         // footnotetexts an error was in.
3824                         foot += "}%\n";
3825                         foot_texrow.newline();
3826                 } else {
3827                         file += '}';
3828                 }
3829                 break;
3830         case LyXParagraph::MARGIN:
3831                 file += '}';
3832                 break;
3833         case LyXParagraph::FIG:
3834                 if (pextra_type == PEXTRA_FLOATFLT
3835                     && (!pextra_width.empty()
3836                         || !pextra_widthp.empty()))
3837                         file += "\\end{floatingfigure}";
3838                 else
3839                         file += "\\end{figure}";
3840                 break;
3841         case LyXParagraph::TAB:
3842                 file += "\\end{table}";
3843                 break;
3844         case LyXParagraph::WIDE_FIG:
3845                 file += "\\end{figure*}";
3846                 break;
3847         case LyXParagraph::WIDE_TAB:
3848                 file += "\\end{table*}";
3849                 break;
3850         case LyXParagraph::ALGORITHM:
3851                 file += "\\end{algorithm}";
3852                 break;
3853         }
3854
3855         if (footnotekind != LyXParagraph::FOOTNOTE
3856             && footnotekind != LyXParagraph::MARGIN) {
3857                 // we need to ensure that real floats like tables and figures
3858                 // have their \end{} on a line of their own otherwise we can
3859                 // get incorrect results when using the endfloat.sty package.
3860                 file += "\n";
3861                 texrow.newline();
3862         }
3863
3864         lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
3865         return par;
3866 }
3867
3868
3869 void LyXParagraph::SetPExtraType(int type, char const * width,
3870                                  char const * widthp)
3871 {
3872         pextra_type = type;
3873         pextra_width = width;
3874         pextra_widthp = widthp;
3875
3876         if (textclasslist.Style(current_view->buffer()->params.textclass, 
3877                                 layout).isEnvironment()) {
3878                 LyXParagraph
3879                         * par = this,
3880                         * ppar = par;
3881
3882                 while (par && (par->layout == layout)
3883                        && (par->depth == depth)) {
3884                         ppar = par;
3885                         par = par->Previous();
3886                         if (par)
3887                                 par = par->FirstPhysicalPar();
3888                         while (par && par->depth > depth) {
3889                                 par = par->Previous();
3890                                 if (par)
3891                                         par = par->FirstPhysicalPar();
3892                         }
3893                 }
3894                 par = ppar;
3895                 while (par && (par->layout == layout)
3896                        && (par->depth == depth)) {
3897                         par->pextra_type = type;
3898                         par->pextra_width = width;
3899                         par->pextra_widthp = widthp;
3900                         par = par->NextAfterFootnote();
3901                         if (par && (par->depth > depth))
3902                                 par->SetPExtraType(type, width, widthp);
3903                         while (par && ((par->depth > depth) || par->IsDummy()))
3904                                 par = par->NextAfterFootnote();
3905                 }
3906         }
3907 }
3908
3909
3910 void LyXParagraph::UnsetPExtraType()
3911 {
3912         if (pextra_type == PEXTRA_NONE)
3913                 return;
3914     
3915         pextra_type = PEXTRA_NONE;
3916         pextra_width.clear();
3917         pextra_widthp.clear();
3918
3919         if (textclasslist.Style(current_view->buffer()->params.textclass, 
3920                                 layout).isEnvironment()) {
3921                 LyXParagraph
3922                         * par = this,
3923                         * ppar = par;
3924
3925                 while (par && (par->layout == layout)
3926                        && (par->depth == depth)) {
3927                         ppar = par;
3928                         par = par->Previous();
3929                         if (par)
3930                                 par = par->FirstPhysicalPar();
3931                         while (par && par->depth > depth) {
3932                                 par = par->Previous();
3933                                 if (par)
3934                                         par = par->FirstPhysicalPar();
3935                         }
3936                 }
3937                 par = ppar;
3938                 while (par && (par->layout == layout)
3939                        && (par->depth == depth)) {
3940                         par->pextra_type = PEXTRA_NONE;
3941                         par->pextra_width.clear();
3942                         par->pextra_widthp.clear();
3943                         par = par->NextAfterFootnote();
3944                         if (par && (par->depth > depth))
3945                                 par->UnsetPExtraType();
3946                         while (par && ((par->depth > depth) || par->IsDummy()))
3947                                 par = par->NextAfterFootnote();
3948                 }
3949         }
3950 }
3951
3952
3953 bool LyXParagraph::IsHfill(size_type pos) const
3954 {
3955         return IsHfillChar(GetChar(pos));
3956 }
3957
3958
3959 bool LyXParagraph::IsInset(size_type pos) const
3960 {
3961         return IsInsetChar(GetChar(pos));
3962 }
3963
3964
3965 bool LyXParagraph::IsFloat(size_type pos) const
3966 {
3967         return IsFloatChar(GetChar(pos));
3968 }
3969
3970
3971 bool LyXParagraph::IsNewline(size_type pos) const
3972 {
3973         bool tmp = false;
3974         if (pos >= 0)
3975                 tmp = IsNewlineChar(GetChar(pos));
3976         return tmp;
3977 }
3978
3979
3980 bool LyXParagraph::IsSeparator(size_type pos) const
3981 {
3982         return IsSeparatorChar(GetChar(pos));
3983 }
3984
3985
3986 bool LyXParagraph::IsLineSeparator(size_type pos) const
3987 {
3988         return IsLineSeparatorChar(GetChar(pos));
3989 }
3990
3991
3992 bool LyXParagraph::IsKomma(size_type pos) const
3993 {
3994         return IsKommaChar(GetChar(pos));
3995 }
3996
3997
3998 /// Used by the spellchecker
3999 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4000 {
4001         unsigned char c = GetChar(pos);
4002         if (IsLetterChar(c))
4003                 return true;
4004         // '\0' is not a letter, allthough every string contains "" (below)
4005         if( c == '\0')
4006                 return false;
4007         // We want to pass the ' and escape chars to ispell
4008         string extra = lyxrc->isp_esc_chars + '\'';
4009         char ch[2];
4010         ch[0] = c;
4011         ch[1] = 0;
4012         return contains(extra, ch);
4013 }
4014  
4015  
4016 bool LyXParagraph::IsWord(size_type pos ) const
4017 {
4018         return IsWordChar(GetChar(pos)) ;
4019 }
4020
4021
4022 LyXDirection LyXParagraph::getParDirection() const
4023 {
4024         if (!lyxrc->rtl_support || table)
4025                 return LYX_DIR_LEFT_TO_RIGHT;
4026
4027         if (size() > 0)
4028                 return (getFont(0).direction() ==  LyXFont::RTL_DIR)
4029                         ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT;
4030         else
4031                 return current_view->buffer()->params.getDocumentDirection();
4032 }
4033
4034
4035 LyXDirection
4036 LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const
4037 {
4038         if (!lyxrc->rtl_support)
4039                 return LYX_DIR_LEFT_TO_RIGHT;
4040
4041         LyXDirection direction = getFont(pos).getFontDirection();
4042         if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1
4043             && !IsLineSeparator(pos + 1)
4044             && !(table && IsNewline(pos + 1))
4045             && (getFont(pos - 1).getFontDirection() != direction
4046                 || getFont(pos + 1).getFontDirection() != direction))
4047                 return getParDirection();
4048         else
4049                 return direction;
4050 }