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