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