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