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