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