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