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