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