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