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