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