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