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