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