]> git.lyx.org Git - lyx.git/blob - src/paragraph.C
49439cd2613a35f0040f3a0af802319b571887c5
[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(istream & is)
2230 {
2231         is.seekg(0);
2232         char c = 0;
2233         while(!is.eof()) {
2234                 is.get(c);
2235                 InsertChar(text.size(), c);
2236         };
2237 }
2238
2239
2240 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
2241                                        string & foot, TexRow & foot_texrow,
2242                                        int & foot_count)
2243 {
2244         lyxerr[Debug::LATEX] << "TeXOnePar...     " << this << endl;
2245         LyXParagraph * par = next;
2246         LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
2247                                                       layout);
2248
2249         bool further_blank_line = false;
2250         if (IsDummy())
2251                 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2252
2253         if (start_of_appendix) {
2254                 file += "\\appendix\n";
2255                 texrow.newline();
2256         }
2257
2258         if (tex_code_break_column && style.isCommand()){
2259                 file += '\n';
2260                 texrow.newline();
2261         }
2262
2263         if (pagebreak_top) {
2264                 file += "\\newpage";
2265                 further_blank_line = true;
2266         }
2267         if (added_space_top.kind() != VSpace::NONE) {
2268                 file += added_space_top.asLatexCommand();
2269                 further_blank_line = true;
2270         }
2271       
2272         if (line_top) {
2273                 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
2274                 file += "\\vspace{-1\\parskip}";
2275                 further_blank_line = true;
2276         }
2277
2278         if (further_blank_line){
2279                 file += '\n';
2280                 texrow.newline();
2281         }
2282
2283         switch (style.latextype) {
2284         case LATEX_COMMAND:
2285                 file += '\\';
2286                 file += style.latexname();
2287                 file += style.latexparam();
2288                 break;
2289         case LATEX_ITEM_ENVIRONMENT:
2290                 if (bibkey) 
2291                         bibkey->Latex(file, false);
2292                 else
2293                         file += "\\item ";
2294                 break;
2295         case LATEX_LIST_ENVIRONMENT:
2296                 file += "\\item ";
2297                 break;
2298         default:
2299                 break;
2300         }
2301
2302         bool need_par = SimpleTeXOnePar(file, texrow);
2303  
2304         // Spit out footnotes
2305         while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2306                && par->footnoteflag != footnoteflag) {
2307                 par = par->TeXFootnote(file, texrow,
2308                                        foot, foot_texrow, foot_count);
2309                 par->SimpleTeXOnePar(file, texrow);
2310                 par = par->next;
2311         }
2312
2313         // Make sure that \\par is done with the font of the last
2314         // character if this has another size as the default.
2315         // This is necessary because LaTeX (and LyX on the screen)
2316         // calculates the space between the baselines according
2317         // to this font. (Matthias)
2318         LyXFont font = getFont(Last()-1);
2319         if (need_par) {
2320                 if (style.resfont.size() != font.size()) {
2321                         file += '\\';
2322                         file += font.latexSize();
2323                         file += ' ';
2324                 }
2325                 file += "\\par}";
2326         } else if (textclasslist.Style(GetCurrentTextClass(),
2327                                        GetLayout()).isCommand()){
2328                 if (style.resfont.size() != font.size()) {
2329                         file += '\\';
2330                         file += font.latexSize();
2331                         file += ' ';
2332                 }
2333                 file += '}';
2334         } else if (style.resfont.size() != font.size()){
2335                 file += "{\\" + font.latexSize() + " \\par}";
2336         }
2337         
2338         switch (style.latextype) {
2339         case LATEX_ITEM_ENVIRONMENT:
2340         case LATEX_LIST_ENVIRONMENT:
2341                 if (par && (depth < par->depth)) {
2342                         file += '\n';
2343                         texrow.newline();
2344                 }
2345                 break;
2346         case LATEX_ENVIRONMENT:
2347                 // if its the last paragraph of the current environment
2348                 // skip it otherwise fall through
2349                 if (par
2350                     && (par->layout != layout
2351                         || par->depth != depth
2352                         || par->pextra_type != pextra_type))
2353                         break;
2354         default:
2355                 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2356                       && footnotekind != LyXParagraph::FOOTNOTE
2357                       && footnotekind != LyXParagraph::MARGIN
2358                       && (table
2359                           || (par
2360                               && par->table)))) {
2361                         // don't insert this if we would be adding it
2362                         // before or after a table in a float.  This 
2363                         // little trick is needed in order to allow
2364                         // use of tables in \subfigures or \subtables.
2365                         file += '\n';
2366                         texrow.newline();
2367                 }
2368         }
2369         
2370         further_blank_line = false;
2371         if (line_bottom) {
2372                 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2373                 further_blank_line = true;
2374         }
2375
2376         if (added_space_bottom.kind() != VSpace::NONE) {
2377                 file += added_space_bottom.asLatexCommand();
2378                 further_blank_line = true;
2379         }
2380       
2381         if (pagebreak_bottom) {
2382                 file += "\\newpage";
2383                 further_blank_line = true;
2384         }
2385
2386         if (further_blank_line){
2387                 file += '\n';
2388                 texrow.newline();
2389         }
2390
2391         if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2392               par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2393                 file += '\n';
2394                 texrow.newline();
2395         }
2396
2397         lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2398         return par;
2399 }
2400
2401
2402 // This one spits out the text of the paragraph
2403 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2404 {
2405         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...     " << this << endl;
2406
2407         if (table)
2408                 return SimpleTeXOneTablePar(file, texrow);
2409
2410         char c;
2411         size_type main_body;
2412         
2413         bool return_value = false;
2414
2415         LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
2416         LyXFont basefont;
2417
2418         /* maybe we have to create a optional argument */ 
2419         if (style.labeltype != LABEL_MANUAL)
2420                 main_body = 0;
2421         else
2422                 main_body = BeginningOfMainBody();
2423
2424         if (main_body > 0) {
2425                 file += '[';
2426                 basefont = getFont(-2); // Get label font
2427         } else {
2428                 basefont = getFont(-1); // Get layout font
2429         }
2430
2431         int column = 0;
2432
2433         if (main_body >= 0
2434             && !text.size()
2435             && !IsDummy()) {
2436                 if (style.isCommand()) {
2437                         file += '{';
2438                         column++;
2439                 } else if (align != LYX_ALIGN_LAYOUT) {
2440                         file += '{';
2441                         column++;
2442                         return_value = true;
2443                 }
2444         }
2445  
2446         // Which font is currently active?
2447         LyXFont running_font = basefont;
2448         // Do we have an open font change?
2449         bool open_font = false;
2450
2451         texrow.start(this, 0);
2452
2453         for (size_type i = 0; i < size(); ++i) {
2454                 column++;
2455                 // First char in paragraph or after label?
2456                 if (i == main_body && !IsDummy()) {
2457                         if (main_body > 0) {
2458                                 if (open_font) {
2459                                         column += running_font.latexWriteEndChanges(file, basefont);
2460                                         open_font = false;
2461                                 }
2462                                 basefont = getFont(-1); // Now use the layout font
2463                                 running_font = basefont;
2464                                 file += ']';
2465                                 column++;
2466                         }
2467                         if (style.isCommand()) {
2468                                 file += '{';
2469                                 column++;
2470                         } else if (align != LYX_ALIGN_LAYOUT) {
2471                                 file += "{\\par";
2472                                 column += 4;
2473                                 return_value = true;
2474                         }
2475
2476                         if (noindent) {
2477                                 file += "\\noindent ";
2478                                 column += 10;
2479                         }
2480                         switch (align) {
2481                         case LYX_ALIGN_NONE:
2482                         case LYX_ALIGN_BLOCK:
2483                         case LYX_ALIGN_LAYOUT:
2484                         case LYX_ALIGN_SPECIAL: break;
2485                         case LYX_ALIGN_LEFT:
2486                                 file += "\\raggedright ";
2487                                 column+= 13;
2488                                 break;
2489                         case LYX_ALIGN_RIGHT:
2490                                 file += "\\raggedleft ";
2491                                 column+= 12;
2492                                 break;
2493                         case LYX_ALIGN_CENTER:
2494                                 file += "\\centering ";
2495                                 column+= 11;
2496                                 break;
2497                         }        
2498                 }
2499
2500                 c = GetChar(i);
2501
2502                 // Fully instantiated font
2503                 LyXFont font = getFont(i);
2504
2505                 // Spaces at end of font change are simulated to be
2506                 // outside font change, i.e. we write "\textXX{text} "
2507                 // rather than "\textXX{text }". (Asger)
2508                 if (open_font && c == ' ' && i <= size() - 2 
2509                     && !getFont(i+1).equalExceptLatex(running_font) 
2510                     && !getFont(i+1).equalExceptLatex(font)) {
2511                         font = getFont(i+1);
2512                 }
2513                 // We end font definition before blanks
2514                 if (!font.equalExceptLatex(running_font) && open_font) {
2515                         column += running_font.latexWriteEndChanges(file,
2516                                                                     basefont);
2517                         running_font = basefont;
2518                         open_font = false;
2519                 }
2520
2521                 // Blanks are printed before start of fontswitch
2522                 if (c == ' '){
2523                         // Do not print the separation of the optional argument
2524                         if (i != main_body - 1) {
2525                                 SimpleTeXBlanks(file, texrow, i,
2526                                                 column, font, style);
2527                         }
2528                 }
2529
2530                 // Do we need to change font?
2531                 if (!font.equalExceptLatex(running_font)
2532                     && i != main_body-1) {
2533                         column += font.latexWriteStartChanges(file, basefont);
2534                         running_font = font;
2535                         open_font = true;
2536                 }
2537
2538                 if (c == LyXParagraph::META_NEWLINE) {
2539                         // newlines are handled differently here than
2540                         // the default in SimpleTeXSpecialChars().
2541                         if (!style.newline_allowed
2542                             || font.latex() == LyXFont::ON) {
2543                                 file += '\n';
2544                         } else {
2545                                 if (open_font) {
2546                                         column += running_font.latexWriteEndChanges(file, basefont);
2547                                         open_font = false;
2548                                 }
2549                                 basefont = getFont(-1);
2550                                 running_font = basefont;
2551                                 if (font.family() == 
2552                                     LyXFont::TYPEWRITER_FAMILY) {
2553                                         file += "~";
2554                                 }
2555                                 file += "\\\\\n";
2556                         }
2557                         texrow.newline();
2558                         texrow.start(this, i+1);
2559                         column = 0;
2560                 } else {
2561                         SimpleTeXSpecialChars(file, texrow,
2562                                               font, running_font, basefont,
2563                                               open_font, style, i, column, c);
2564                 }
2565         }
2566
2567         // If we have an open font definition, we have to close it
2568         if (open_font) {
2569                 running_font.latexWriteEndChanges(file, basefont);
2570         }
2571
2572         /* needed if there is an optional argument but no contents */ 
2573         if (main_body > 0 && main_body == size()) {
2574                 file += "]~";
2575                 return_value = false;
2576         }
2577
2578         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2579         return return_value;
2580 }
2581
2582
2583 // This one spits out the text of a table paragraph
2584 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2585 {
2586         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...     " << this << endl;
2587         char c;
2588         int tmp;
2589    
2590         bool return_value = false;
2591         int current_cell_number = -1;
2592
2593         LyXLayout const & style = 
2594                 textclasslist.Style(GetCurrentTextClass(), GetLayout());
2595         LyXFont basefont = getFont(-1); // Get layout font
2596         // Which font is currently active?
2597         LyXFont running_font = basefont;
2598         // Do we have an open font change?
2599         bool open_font = false;
2600  
2601         int column = 0;
2602         if (!IsDummy()) { // it is dummy if it is in a float!!!
2603                 if (style.isCommand()) {
2604                         file += '{';
2605                         column++;
2606                 } else if (align != LYX_ALIGN_LAYOUT) {
2607                         file += '{';
2608                         column++;
2609                         return_value = true;
2610                 }
2611                 if (noindent) {
2612                         file += "\\noindent ";
2613                         column += 10;
2614                 }
2615                 switch (align) {
2616                 case LYX_ALIGN_NONE:
2617                 case LYX_ALIGN_BLOCK:
2618                 case LYX_ALIGN_LAYOUT:
2619                 case LYX_ALIGN_SPECIAL: break;
2620                 case LYX_ALIGN_LEFT:
2621                         file += "\\raggedright ";
2622                         column+= 13;
2623                         break;
2624                 case LYX_ALIGN_RIGHT:
2625                         file += "\\raggedleft ";
2626                         column+= 12;
2627                         break;
2628                 case LYX_ALIGN_CENTER:
2629                         file += "\\centering ";
2630                         column+= 11;
2631                         break;
2632                 }
2633         }
2634         current_cell_number = -1;
2635         tmp = table->TexEndOfCell(file, current_cell_number);
2636         for (; tmp > 0 ; --tmp)
2637                 texrow.newline();
2638         
2639         texrow.start(this, 0);
2640
2641         for (size_type i = 0; i < size(); ++i) {
2642                 c = GetChar(i);
2643                 if (table->IsContRow(current_cell_number+1)) {
2644                         if (c == LyXParagraph::META_NEWLINE)
2645                                 current_cell_number++;
2646                         continue;
2647                 }
2648                 ++column;
2649                 
2650                 // Fully instantiated font
2651                 LyXFont font = getFont(i);
2652
2653                 // Spaces at end of font change are simulated to be
2654                 // outside font change.
2655                 // i.e. we write "\textXX{text} " rather than
2656                 // "\textXX{text }". (Asger)
2657                 if (open_font && c == ' ' && i <= size() - 2
2658                     && getFont(i+1) != running_font && getFont(i+1) != font) {
2659                         font = getFont(i+1);
2660                 }
2661
2662                 // We end font definition before blanks
2663                 if (font != running_font && open_font) {
2664                         column += running_font.latexWriteEndChanges(file,
2665                                                                     basefont);
2666                         running_font = basefont;
2667                         open_font = false;
2668                 }
2669                 // Blanks are printed before start of fontswitch
2670                 if (c == ' '){
2671                         SimpleTeXBlanks(file, texrow, i, column, font, style);
2672                 }
2673                 // Do we need to change font?
2674                 if (font != running_font) {
2675                         column += font.latexWriteStartChanges(file, basefont);
2676                         running_font = font;
2677                         open_font = true;
2678                 }
2679                 // Do we need to turn on LaTeX mode?
2680                 if (font.latex() != running_font.latex()) {
2681                         if (font.latex() == LyXFont::ON
2682                             && style.needprotect) {
2683                                 file += "\\protect ";
2684                                 column += 9;
2685                         }
2686                 }
2687                 if (c == LyXParagraph::META_NEWLINE) {
2688                         // special case for inside a table
2689                         // different from default case in
2690                         // SimpleTeXSpecialChars()
2691                         if (open_font) {
2692                                 column += running_font
2693                                         .latexWriteEndChanges(file, basefont);
2694                                 open_font = false;
2695                         }
2696                         basefont = getFont(-1);
2697                         running_font = basefont;
2698                         current_cell_number++;
2699                         if (table->CellHasContRow(current_cell_number) >= 0) {
2700                                 TeXContTableRows(file, i+1,
2701                                                  current_cell_number,
2702                                                  column, texrow);
2703                         }
2704                         // if this cell follow only ContRows till end don't
2705                         // put the EndOfCell because it is put after the
2706                         // for(...)
2707                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2708                                 current_cell_number--;
2709                                 break;
2710                         }
2711                         int tmp = table->TexEndOfCell(file,
2712                                                       current_cell_number);
2713                         if (tmp>0) {
2714                                 column = 0;
2715                         } else if (tmp < 0) {
2716                                 tmp = -tmp;
2717                         }
2718                         for (;tmp--;) {
2719                                 texrow.newline();
2720                         }
2721                         texrow.start(this, i+1);
2722                 } else {
2723                         SimpleTeXSpecialChars(file, texrow,
2724                                               font, running_font, basefont,
2725                                               open_font, style, i, column, c);
2726                 }
2727         }
2728
2729         // If we have an open font definition, we have to close it
2730         if (open_font) {
2731                 running_font.latexWriteEndChanges(file, basefont);
2732         }
2733         current_cell_number++;
2734         tmp = table->TexEndOfCell(file, current_cell_number);
2735         for (; tmp > 0; --tmp)
2736                 texrow.newline();
2737         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2738         return return_value;
2739 }
2740
2741
2742 // This one spits out the text off ContRows in tables
2743 bool LyXParagraph::TeXContTableRows(string & file,
2744                                     LyXParagraph::size_type i,
2745                                     int current_cell_number,
2746                                     int & column, TexRow & texrow)
2747 {
2748         lyxerr[Debug::LATEX] << "TeXContTableRows...     " << this << endl;
2749         if (!table)
2750                 return false;
2751     
2752         char c;
2753    
2754         bool return_value = false;
2755         LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
2756                                                       GetLayout());
2757         LyXFont basefont;
2758
2759         basefont = getFont(-1); // Get layout font
2760         // Which font is currently active?
2761         LyXFont running_font = basefont;
2762         // Do we have an open font change?
2763         bool open_font = false;
2764
2765         size_type lastpos = i;
2766         int cell = table->CellHasContRow(current_cell_number);
2767         ++current_cell_number;
2768         while(cell >= 0) {
2769                 // first find the right position
2770                 i = lastpos;
2771                 for (; (i < size()) && (current_cell_number<cell); ++i) {
2772                         c = GetChar(i);
2773                         if (c == LyXParagraph::META_NEWLINE)
2774                                 current_cell_number++;
2775                 }
2776                 lastpos = i;
2777                 c = GetChar(i);
2778                 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2779                         file += " \\\\\n";
2780                         texrow.newline();
2781                         column = 0;
2782                 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2783                         file += ' ';
2784                 }
2785
2786                 for (; i < size()
2787                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2788                      ++i) {
2789                         ++column;
2790
2791                         // Fully instantiated font
2792                         LyXFont font = getFont(i);
2793
2794                         // Spaces at end of font change are simulated to
2795                         // be outside font change. i.e. we write
2796                         // "\textXX{text} " rather than "\textXX{text }".
2797                         // (Asger)
2798                         if (open_font && c == ' ' && i <= size() - 2 
2799                             && getFont(i + 1) != running_font
2800                             && getFont(i + 1) != font) {
2801                                 font = getFont(i + 1);
2802                         }
2803
2804                         // We end font definition before blanks
2805                         if (font != running_font && open_font) {
2806                                 column += running_font.latexWriteEndChanges(file, basefont);
2807                                 running_font = basefont;
2808                                 open_font = false;
2809                         }
2810                         // Blanks are printed before start of fontswitch
2811                         if (c == ' '){
2812                                 SimpleTeXBlanks(file, texrow, i,
2813                                                 column, font, style);
2814                         }
2815                         // Do we need to change font?
2816                         if (font != running_font) {
2817                                 column +=
2818                                         font.latexWriteStartChanges(file,
2819                                                                     basefont);
2820                                 running_font = font;
2821                                 open_font = true;
2822                         }
2823                         // Do we need to turn on LaTeX mode?
2824                         if (font.latex() != running_font.latex()) {
2825                                 if (font.latex() == LyXFont::ON
2826                                     && style.needprotect)
2827                                         {
2828                                                 file += "\\protect ";
2829                                                 column += 9;
2830                                         }
2831                         }
2832                         SimpleTeXSpecialChars(file, texrow, font,
2833                                               running_font, basefont,
2834                                               open_font, style, i, column, c);
2835                 }
2836                 // If we have an open font definition, we have to close it
2837                 if (open_font) {
2838                         running_font.latexWriteEndChanges(file, basefont);
2839                         open_font = false;
2840                 }
2841                 basefont = getFont(-1);
2842                 running_font = basefont;
2843                 cell = table->CellHasContRow(current_cell_number);
2844         }
2845         lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2846         return return_value;
2847 }
2848
2849
2850 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2851 {
2852         bool retval = false;
2853         switch (c) {
2854         case LyXParagraph::META_HFILL:
2855                 sgml_string.clear();
2856                 break;
2857         case LyXParagraph::META_PROTECTED_SEPARATOR: 
2858                 sgml_string = ' ';
2859                 break;
2860         case LyXParagraph::META_NEWLINE:
2861                 sgml_string = '\n';
2862                 break;
2863         case '&': 
2864                 sgml_string = "&amp;";
2865                 break;
2866         case '<': 
2867                 sgml_string = "&lt;"; 
2868                 break;
2869         case '>':
2870                 sgml_string = "&gt;"; 
2871                 break;
2872         case '$': 
2873                 sgml_string = "&dollar;"; 
2874                 break;
2875         case '#': 
2876                 sgml_string = "&num;";
2877                 break;
2878         case '%': 
2879                 sgml_string = "&percnt;";
2880                 break;
2881         case '[': 
2882                 sgml_string = "&lsqb;";
2883                 break;
2884         case ']': 
2885                 sgml_string = "&rsqb;";
2886                 break;
2887         case '{': 
2888                 sgml_string = "&lcub;";
2889                 break;
2890         case '}': 
2891                 sgml_string = "&rcub;";
2892                 break;
2893         case '~': 
2894                 sgml_string = "&tilde;";
2895                 break;
2896         case '"': 
2897                 sgml_string = "&quot;";
2898                 break;
2899         case '\\': 
2900                 sgml_string = "&bsol;";
2901                 break;
2902         case ' ':
2903                 retval = true;
2904                 sgml_string = ' ';
2905                 break;
2906         case '\0': /* Ignore :-) */
2907                 sgml_string.clear();
2908                 break;
2909         default:
2910                 sgml_string = c;
2911                 break;
2912         }
2913         return retval;
2914 }
2915
2916
2917 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
2918                                             int & desc_on, int depth) 
2919 {
2920         if (!table) return;
2921         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2922         int column;
2923         LyXFont font1, font2;
2924         char c;
2925         Inset * inset;
2926         size_type main_body;
2927         string emph = "emphasis";
2928         bool emph_flag = false;
2929         
2930         LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
2931                                                       GetLayout());
2932         
2933         if (style.labeltype != LABEL_MANUAL)
2934                 main_body = 0;
2935         else
2936                 main_body = BeginningOfMainBody();
2937         
2938         /* gets paragraph main font */
2939         if (main_body > 0)
2940                 font1 = style.labelfont;
2941         else
2942                 font1 = style.font;
2943         
2944         int char_line_count = depth;
2945         addNewlineAndDepth(file, depth);
2946         if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2947                 file += "<INFORMALTABLE>";
2948                 addNewlineAndDepth(file, ++depth);
2949         }
2950         int current_cell_number = -1;
2951         int tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2952         
2953         /* parsing main loop */
2954         for (size_type i = 0; i < size(); ++i) {
2955                 c = GetChar(i);
2956                 if (table->IsContRow(current_cell_number+1)) {
2957                         if (c == LyXParagraph::META_NEWLINE)
2958                                 ++current_cell_number;
2959                         continue;
2960                 }
2961                 ++column;
2962                 
2963                 // Fully instantiated font
2964                 font2 = getFont(i);
2965                 
2966                 /* handle <emphasis> tag */
2967                 if (font1.emph() != font2.emph() && i) {
2968                         if (font2.emph() == LyXFont::ON) {
2969                                 file += "<emphasis>";
2970                                 emph_flag= true;
2971                         } else if (emph_flag) {
2972                                 file += "</emphasis>";
2973                                 emph_flag= false;
2974                         }
2975                 }
2976                 if (c == LyXParagraph::META_NEWLINE) {
2977                         // we have only to control for emphasis open here!
2978                         if (emph_flag) {
2979                                 file += "</emphasis>";
2980                                 emph_flag= false;
2981                         }
2982                         font1 = font2 = getFont(-1);
2983                         current_cell_number++;
2984                         if (table->CellHasContRow(current_cell_number) >= 0) {
2985                                 DocBookContTableRows(file, extra, desc_on, i+1,
2986                                                      current_cell_number,
2987                                                      column);
2988                         }
2989                         // if this cell follow only ContRows till end don't
2990                         // put the EndOfCell because it is put after the
2991                         // for(...)
2992                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2993                                 current_cell_number--;
2994                                 break;
2995                         }
2996                         tmp= table->DocBookEndOfCell(file, current_cell_number,
2997                                                      depth);
2998                         
2999                         if (tmp > 0)
3000                                 column = 0;
3001                 } else if (c == LyXParagraph::META_INSET) {
3002                         inset = GetInset(i);
3003                         string tmp_out;
3004                         inset->DocBook(tmp_out);
3005                         //
3006                         // This code needs some explanation:
3007                         // Two insets are treated specially
3008                         //   label if it is the first element in a
3009                         //   command paragraph
3010                         //         desc_on == 3
3011                         //   graphics inside tables or figure floats
3012                         //   can't go on
3013                         //   title (the equivalente in latex for this
3014                         //   case is caption
3015                         //   and title should come first
3016                         //         desc_on == 4
3017                         //
3018                         if(desc_on != 3 || i != 0) {
3019                                 if(tmp_out[0] == '@') {
3020                                         if(desc_on == 4)
3021                                                 extra += frontStrip(tmp_out,
3022                                                                     '@');
3023                                         else
3024                                                 file += frontStrip(tmp_out,
3025                                                                    '@');
3026                                 } else
3027                                         file += tmp_out;
3028                         }
3029                 } else if (font2.latex() == LyXFont::ON) {
3030                         // "TeX"-Mode on == > SGML-Mode on.
3031                         if (c != '\0')
3032                                 file += c;
3033                         char_line_count++;
3034                 } else {
3035                         string sgml_string;
3036                         if (linuxDocConvertChar(c, sgml_string) 
3037                             && !style.free_spacing) {
3038                                 // in freespacing mode, spaces are
3039                                 // non-breaking characters
3040                                 // char is ' '
3041                                 if (desc_on == 1) {
3042                                         char_line_count++;
3043                                         file += '\n';
3044                                         file += "</term><listitem><para>";
3045                                         desc_on = 2;
3046                                 } else  {
3047                                         file += c;
3048                                 }
3049                         } else {
3050                                 file += sgml_string;
3051                         }
3052                 }
3053                 font1 = font2;
3054         }
3055         
3056         /* needed if there is an optional argument but no contents */
3057         if (main_body > 0 && main_body == size()) {
3058                 font1 = style.font;
3059         }
3060
3061         if (emph_flag) {
3062                 file += "</emphasis>";
3063         }
3064         
3065         current_cell_number++;
3066         tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3067         /* resets description flag correctly */
3068         switch(desc_on){
3069         case 1:
3070                 /* <term> not closed... */
3071                 file += "</term>";
3072                 break;
3073         }
3074         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3075                 file += "</INFORMALTABLE>";
3076         file += '\n';
3077         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3078                              << this << endl;
3079 }
3080
3081
3082 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3083                                         int & desc_on,
3084                                         LyXParagraph::size_type i,
3085                                         int current_cell_number, int &column) 
3086
3087 {
3088         if (!table) return;
3089         
3090         lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3091
3092         int cell;
3093         LyXFont font1, font2;
3094         char c;
3095         Inset * inset;
3096         size_type main_body;
3097         size_type lastpos;
3098         string emph= "emphasis";
3099         bool emph_flag= false;
3100         int char_line_count= 0;
3101         
3102         LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
3103                                                       GetLayout());
3104         
3105         if (style.labeltype != LABEL_MANUAL)
3106                 main_body = 0;
3107         else
3108                 main_body = BeginningOfMainBody();
3109         
3110         /* gets paragraph main font */
3111         if (main_body > 0)
3112                 font1 = style.labelfont;
3113         else
3114                 font1 = style.font;
3115         
3116         lastpos = i;
3117         cell = table->CellHasContRow(current_cell_number);
3118         ++current_cell_number;
3119         while(cell >= 0) {
3120                 // first find the right position
3121                 i = lastpos;
3122                 for (; i < size() && current_cell_number < cell; ++i) {
3123                         c = GetChar(i);
3124                         if (c == LyXParagraph::META_NEWLINE)
3125                                 current_cell_number++;
3126                 }
3127                 lastpos = i;
3128                 c = GetChar(i);
3129                 // I don't know how to handle this so I comment it
3130                 // for the moment (Jug)
3131 //             if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3132 //                     file += " \\\\\n";
3133 //                     column = 0;
3134 //             } else
3135                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3136                         file += ' ';
3137                 }
3138
3139                 for (; i < size()
3140                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3141                      ++i) {
3142                         ++column;
3143                         
3144                         // Fully instantiated font
3145                         font2 = getFont(i);
3146                         
3147                         /* handle <emphasis> tag */
3148                         if (font1.emph() != font2.emph() && i) {
3149                                 if (font2.emph() == LyXFont::ON) {
3150                                         file += "<emphasis>";
3151                                         emph_flag= true;
3152                                 } else if (emph_flag) {
3153                                         file += "</emphasis>";
3154                                         emph_flag= false;
3155                                 }
3156                         }
3157                         if (c == LyXParagraph::META_INSET) {
3158                                 inset = GetInset(i);
3159                                 string tmp_out;
3160                                 inset->DocBook(tmp_out);
3161                                 //
3162                                 // This code needs some explanation:
3163                                 // Two insets are treated specially
3164                                 //   label if it is the first element in a command paragraph
3165                                 //       desc_on == 3
3166                                 //   graphics inside tables or figure floats can't go on
3167                                 //   title (the equivalente in latex for this case is caption
3168                                 //   and title should come first
3169                                 //       desc_on == 4
3170                                 //
3171                                 if(desc_on != 3 || i != 0) {
3172                                         if(tmp_out[0] == '@') {
3173                                                 if(desc_on == 4)
3174                                                         extra += frontStrip(tmp_out, '@');
3175                                                 else
3176                                                         file += frontStrip(tmp_out, '@');
3177                                         } else
3178                                                 file += tmp_out;
3179                                 }
3180                         } else if (font2.latex() == LyXFont::ON) {
3181                                 // "TeX"-Mode on == > SGML-Mode on.
3182                                 if (c!= '\0')
3183                                         file += c;
3184                                 char_line_count++;
3185                         } else {
3186                                 string sgml_string;
3187                                 if (linuxDocConvertChar(c, sgml_string) 
3188                                     && !style.free_spacing) {
3189                                 // in freespacing mode, spaces are
3190                                 // non-breaking characters
3191                                 // char is ' '
3192                                         if (desc_on == 1) {
3193                                                 char_line_count++;
3194                                                 file += '\n';
3195                                                 file += "</term><listitem><para>";
3196                                                 desc_on = 2;
3197                                         } else  {
3198                                                 file += c;
3199                                         }
3200                                 } else {
3201                                         file += sgml_string;
3202                                 }
3203                         }
3204                 }
3205                 // we have only to control for emphasis open here!
3206                 if (emph_flag) {
3207                         file += "</emphasis>";
3208                         emph_flag= false;
3209                 }
3210                 font1 = font2 = getFont(-1);
3211                 cell = table->CellHasContRow(current_cell_number);
3212         }
3213         lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3214 }
3215
3216
3217 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3218                                    LyXParagraph::size_type const i,
3219                                    int & column, LyXFont const & font,
3220                                    LyXLayout const & style)
3221 {
3222         if (column > tex_code_break_column
3223             && i 
3224             && GetChar(i - 1) != ' '
3225             && (i < size() - 1)
3226             // In LaTeX mode, we don't want to
3227             // break lines since some commands
3228             // do not like this
3229             && ! (font.latex() == LyXFont::ON)
3230             // same in FreeSpacing mode
3231             && !style.free_spacing
3232             // In typewriter mode, we want to avoid 
3233             // ! . ? : at the end of a line
3234             && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3235                  && (GetChar(i-1) == '.'
3236                      || GetChar(i-1) == '?' 
3237                      || GetChar(i-1) == ':'
3238                      || GetChar(i-1) == '!'))) {
3239                 if (tex_code_break_column == 0) {
3240                         // in batchmode we need LaTeX to still
3241                         // see it as a space not as an extra '\n'
3242                         file += " %\n";
3243                 } else {
3244                         file += '\n';
3245                 }
3246                 texrow.newline();
3247                 texrow.start(this, i+1);
3248                 column = 0;
3249         } else if (font.latex() == LyXFont::OFF) {
3250                 if (style.free_spacing) {
3251                         file += '~';
3252                 } else {
3253                         file += ' ';
3254                 }
3255         }
3256 }
3257
3258
3259 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
3260                                          LyXFont & font,
3261                                          LyXFont & running_font,
3262                                          LyXFont & basefont,
3263                                          bool & open_font,
3264                                          LyXLayout const & style,
3265                                          LyXParagraph::size_type & i,
3266                                          int & column, char const c)
3267 {
3268         // Two major modes:  LaTeX or plain
3269         // Handle here those cases common to both modes
3270         // and then split to handle the two modes separately.
3271         switch (c) {
3272         case LyXParagraph::META_INSET: {
3273                 Inset * inset = GetInset(i);
3274                 if (inset) {
3275                         int len = file.length();
3276                         int tmp = inset->Latex(file, style.isCommand());
3277                         
3278                         if (tmp) {
3279                                 column = 0;
3280                         } else {
3281                                 column += file.length() - len;
3282                         }
3283                         for (;tmp--;) {
3284                                 texrow.newline();
3285                         }
3286                 }
3287         }
3288         break;
3289
3290         case LyXParagraph::META_NEWLINE:
3291                 if (open_font) {
3292                         column += running_font.latexWriteEndChanges(file,
3293                                                                     basefont);
3294                         open_font = false;
3295                 }
3296                 basefont = getFont(-1);
3297                 running_font = basefont;
3298                 break;
3299
3300         case LyXParagraph::META_HFILL: 
3301                 file += "\\hfill{}";
3302                 column += 7;
3303                 break;
3304
3305         default:
3306                 // And now for the special cases within each mode
3307                 // Are we in LaTeX mode?
3308                 if (font.latex() == LyXFont::ON) {
3309                         // at present we only have one option
3310                         // but I'll leave it as a switch statement
3311                         // so its simpler to extend. (ARRae)
3312                         switch (c) {
3313                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
3314                                 file += ' ';
3315                                 break;
3316
3317                         default:
3318                                 // make sure that we will not print
3319                                 // error generating chars to the tex
3320                                 // file. This test would not be needed
3321                                 // if it were done in the buffer
3322                                 // itself.
3323                                 if (c != '\0') {
3324                                         file += c;
3325                                 }
3326                                 break;
3327                         }
3328                 } else {
3329                         // Plain mode (i.e. not LaTeX)
3330                         switch (c) {
3331                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
3332                                 file += '~';
3333                                 break;
3334
3335                         case '\\': 
3336                                 file += "\\textbackslash{}";
3337                                 column += 15;
3338                                 break;
3339                 
3340                         case '°': case '±': case '²': case '³':  
3341                         case '×': case '÷': case '¹': case 'ª':
3342                         case 'º': case '¬': case 'µ':
3343                                 if (current_view->buffer()->params.inputenc == "latin1") {
3344                                         file += "\\ensuremath{";
3345                                         file += c;
3346                                         file += '}';
3347                                         column += 13;
3348                                 } else {
3349                                         file += c;
3350                                 }
3351                                 break;
3352
3353                         case '|': case '<': case '>':
3354                                 // In T1 encoding, these characters exist
3355                                 if (lyxrc->fontenc == "T1") {
3356                                         file += c;
3357                                         //... but we should avoid ligatures
3358                                         if ((c == '>' || c == '<')
3359                                             && i <= size() - 2
3360                                             && GetChar(i+1) == c){
3361                                                 file += "\\textcompwordmark{}";
3362                                                 column += 19;
3363                                         }
3364                                         break;
3365                                 }
3366                                 // Typewriter font also has them
3367                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3368                                         file += c;
3369                                         break;
3370                                 } 
3371                                 // Otherwise, we use what LaTeX
3372                                 // provides us.
3373                                 switch(c) {
3374                                 case '<':
3375                                         file += "\\textless{}";
3376                                         column += 10;
3377                                         break;
3378                                 case '>':
3379                                         file += "\\textgreater{}";
3380                                         column += 13;
3381                                         break;
3382                                 case '|':
3383                                         file += "\\textbar{}";
3384                                         column += 9;
3385                                         break;
3386                                 }
3387                                 break;
3388
3389                         case '-': // "--" in Typewriter mode -> "-{}-"
3390                                 if (i <= size() - 2
3391                                     && GetChar(i + 1) == '-'
3392                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3393                                         file += "-{}";
3394                                         column += 2;
3395                                 } else {
3396                                         file += '-';
3397                                 }
3398                                 break;
3399
3400                         case '\"': 
3401                                 file += "\\char`\\\"{}";
3402                                 column += 9;
3403                                 break;
3404
3405                         case '£':
3406                                 if (current_view->buffer()->params.inputenc == "default") {
3407                                         file += "\\pounds{}";
3408                                         column += 8;
3409                                 } else {
3410                                         file += c;
3411                                 }
3412                                 break;
3413
3414                         case '$': case '&':
3415                         case '%': case '#': case '{':
3416                         case '}': case '_':
3417                                 file += '\\';
3418                                 file += c;
3419                                 column += 1;
3420                                 break;
3421
3422                         case '~':
3423                                 file += "\\textasciitilde{}";
3424                                 column += 16;
3425                                 break;
3426
3427                         case '^':
3428                                 file += "\\textasciicircum{}";
3429                                 column += 17;
3430                                 break;
3431
3432                         case '*': case '[': case ']':
3433                                 // avoid being mistaken for optional arguments
3434                                 file += '{';
3435                                 file += c;
3436                                 file += '}';
3437                                 column += 2;
3438                                 break;
3439
3440                         case ' ':
3441                                 /* blanks are printed before font switching */
3442                                 // Sure? I am not! (try nice-latex)
3443                                 // I am sure it's correct. LyX might be smarter
3444                                 // in the future, but for now, nothing wrong is
3445                                 // written. (Asger)
3446                                 break;
3447
3448                         default:
3449                                 /* idea for labels --- begin*/
3450                                 /* check for LyX */
3451                                 if (c ==  'L'
3452                                     && i <= size() - 3
3453                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
3454                                     && GetChar(i + 1) == 'y'
3455                                     && GetChar(i + 2) == 'X') {
3456                                         file += "\\LyX{}";
3457                                         i += 2;
3458                                         column += 5;
3459                                 }
3460                                 /* check for TeX */ 
3461                                 else if (c == 'T'
3462                                          && i <= size() - 3
3463                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3464                                          && GetChar(i + 1) == 'e'
3465                                          && GetChar(i + 2) == 'X') {
3466                                         file += "\\TeX{}";
3467                                         i += 2;
3468                                         column += 5;
3469                                 }
3470                                 /* check for LaTeX2e */ 
3471                                 else if (c == 'L'
3472                                          && i <= size() - 7
3473                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3474                                          && GetChar(i + 1) == 'a'
3475                                          && GetChar(i + 2) == 'T'
3476                                          && GetChar(i + 3) == 'e'
3477                                          && GetChar(i + 4) == 'X'
3478                                          && GetChar(i + 5) == '2'
3479                                          && GetChar(i + 6) == 'e') {
3480                                         file += "\\LaTeXe{}";
3481                                         i += 6;
3482                                         column += 8;
3483                                 }
3484                                 /* check for LaTeX */ 
3485                                 else if (c == 'L'
3486                                          && i <= size() - 5
3487                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3488                                          && GetChar(i + 1) == 'a'
3489                                          && GetChar(i + 2) == 'T'
3490                                          && GetChar(i + 3) == 'e'
3491                                          && GetChar(i + 4) == 'X') {
3492                                         file += "\\LaTeX{}";
3493                                         i += 4;
3494                                         column += 7;
3495                                         /* idea for labels --- end*/ 
3496                                 } else if (c != '\0') {
3497                                         file += c;
3498                                 }
3499                                 break;
3500                         }
3501                 }
3502         }
3503 }
3504
3505
3506 bool LyXParagraph::RoffContTableRows(ostream & os,
3507                                      LyXParagraph::size_type i,
3508                                      int actcell)
3509 {
3510         if (!table)
3511                 return false;
3512
3513         LyXFont font1 = LyXFont(LyXFont::ALL_INHERIT);
3514         LyXFont font2;
3515         Inset * inset;
3516         char c;
3517
3518         string fname2 = TmpFileName(string(), "RAT2");
3519         int lastpos = i;
3520         int cell = table->CellHasContRow(actcell);
3521         ++actcell;
3522         while(cell >= 0) {
3523                 // first find the right position
3524                 i = lastpos;
3525                 for (; i < size() && actcell < cell; ++i) {
3526                         c = GetChar(i);
3527                         if (c == LyXParagraph::META_NEWLINE)
3528                                 ++actcell;
3529                 }
3530                 lastpos = i;
3531                 c = GetChar(i);
3532                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3533                         os << " ";
3534                 for (; i < size()
3535                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3536                      ++i) {
3537                         font2 = GetFontSettings(i);
3538                         if (font1.latex() != font2.latex()) {
3539                                 if (font2.latex() != LyXFont::OFF)
3540                                         continue;
3541                         }
3542                         c = GetChar(i);
3543                         switch (c) {
3544                         case LyXParagraph::META_INSET:
3545                                 if ((inset = GetInset(i))) {
3546                                         fstream fs(fname2.c_str(),
3547                                                    ios::in|ios::out);
3548                                         if (!fs) {
3549                                                 WriteAlert(_("LYX_ERROR:"),
3550                                                            _("Cannot open temporary file:"),
3551                                                            fname2);
3552                                                 return false;
3553                                         }
3554                                         inset->Latex(fs, -1);
3555                                         fs.seekp(0);
3556                                         fs.get(c);
3557                                         while (!fs) {
3558                                                 if (c == '\\')
3559                                                         os << "\\\\";
3560                                                 else
3561                                                         os << c;
3562                                                 fs.get(c);
3563                                         }
3564                                         fs.close();
3565                                 }
3566                                 break;
3567                         case LyXParagraph::META_NEWLINE:
3568                                 break;
3569                         case LyXParagraph::META_HFILL: 
3570                                 break;
3571                         case LyXParagraph::META_PROTECTED_SEPARATOR:
3572                                 break;
3573                         case '\\': 
3574                                 os << "\\\\";
3575                                 break;
3576                         default:
3577                                 if (c != '\0')
3578                                         os << c;
3579                                 else
3580                                         lyxerr.debug() << "RoffAsciiTable: "
3581                                                 "NULL char in structure."
3582                                                        << endl;
3583                                 break;
3584                         }
3585                 }
3586                 cell = table->CellHasContRow(actcell);
3587         }
3588         return true;
3589 }
3590
3591
3592 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
3593                                        string & foot, TexRow & foot_texrow,
3594                                        int & foot_count)
3595 {
3596         lyxerr[Debug::LATEX] << "TeXDeeper...     " << this << endl;
3597         LyXParagraph * par = this;
3598
3599         while (par && par->depth == depth) {
3600                 if (par->IsDummy())
3601                         lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3602                 if (textclasslist.Style(GetCurrentTextClass(), 
3603                                         par->layout).isEnvironment()
3604                     || par->pextra_type != PEXTRA_NONE) 
3605                         {
3606                                 par = par->TeXEnvironment(file, texrow,
3607                                                           foot, foot_texrow,
3608                                                           foot_count);
3609                         } else {
3610                                 par = par->TeXOnePar(file, texrow,
3611                                                      foot, foot_texrow,
3612                                                      foot_count);
3613                         }
3614         }
3615         lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3616
3617         return par;
3618 }
3619
3620
3621 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
3622                                             string & foot, TexRow & foot_texrow,
3623                                             int & foot_count)
3624 {
3625         bool eindent_open = false;
3626         bool foot_this_level = false;
3627         // flags when footnotetext should be appended to file.
3628         static bool minipage_open = false;
3629         static int minipage_open_depth = 0;
3630         char par_sep = current_view->buffer()->params.paragraph_separation;
3631     
3632         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << this << endl;
3633         if (IsDummy())
3634                 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3635
3636         LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
3637                                                       layout);
3638        
3639         if (pextra_type == PEXTRA_INDENT) {
3640                 if (!pextra_width.empty()) {
3641                         file += "\\begin{LyXParagraphIndent}{"
3642                                 + pextra_width + "}\n";
3643                 } else {
3644                         //float ib = atof(pextra_widthp.c_str())/100;
3645                         // string can't handle floats at present (971109)
3646                         // so I'll do a conversion by hand knowing that
3647                         // the limits are 0.0 to 1.0. ARRae.
3648                         file += "\\begin{LyXParagraphIndent}{";
3649                         switch (pextra_widthp.length()) {
3650                         case 3:
3651                                 file += "1.00";
3652                                 break;
3653                         case 2:
3654                                 file += "0.";
3655                                 file += pextra_widthp;
3656                                 break;
3657                         case 1:
3658                                 file += "0.0";
3659                                 file += pextra_widthp;
3660                         }
3661                         file += "\\columnwidth}\n";
3662                 }
3663                 texrow.newline();
3664                 eindent_open = true;
3665         }
3666         if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3667                 if (pextra_hfill && Previous() &&
3668                     (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3669                         file += "\\hfill{}\n";
3670                         texrow.newline();
3671                 }
3672                 if (par_sep == BufferParams::PARSEP_INDENT) {
3673                         file += "{\\setlength\\parindent{0pt}\n";
3674                         texrow.newline();
3675                 }
3676                 file += "\\begin{minipage}";
3677                 switch(pextra_alignment) {
3678                 case MINIPAGE_ALIGN_TOP:
3679                         file += "[t]";
3680                         break;
3681                 case MINIPAGE_ALIGN_MIDDLE:
3682                         file += "[m]";
3683                         break;
3684                 case MINIPAGE_ALIGN_BOTTOM:
3685                         file += "[b]";
3686                         break;
3687                 }
3688                 if (!pextra_width.empty()) {
3689                         file += '{';
3690                         file += pextra_width + "}\n";
3691                 } else {
3692                         //float ib = atof(par->pextra_width.c_str())/100;
3693                         // string can't handle floats at present
3694                         // so I'll do a conversion by hand knowing that
3695                         // the limits are 0.0 to 1.0. ARRae.
3696                         file += '{';
3697                         switch (pextra_widthp.length()) {
3698                         case 3:
3699                                 file += "1.00";
3700                                 break;
3701                         case 2:
3702                                 file += "0.";
3703                                 file += pextra_widthp;
3704                                 break;
3705                         case 1:
3706                                 file += "0.0";
3707                                 file += pextra_widthp;
3708                         }
3709                         file += "\\columnwidth}\n";
3710                 }
3711                 texrow.newline();
3712                 if (par_sep == BufferParams::PARSEP_INDENT) {
3713                         file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3714                         texrow.newline();
3715                 }
3716                 minipage_open = true;
3717                 minipage_open_depth = depth;
3718         }
3719
3720 #ifdef WITH_WARNINGS
3721 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3722         //I disabled it because it breaks when lists span on several
3723         //pages (JMarc)
3724 #endif
3725         if (style.isEnvironment()){
3726                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3727 #ifdef FANCY_FOOTNOTE_CODE
3728                         if (foot_count < 0) {
3729                                 // flag that footnote[mark][text] should be
3730                                 // used for any footnotes from now on
3731                                 foot_count = 0;
3732                                 foot_this_level = true;
3733                         }
3734 #endif
3735                         file += "\\begin{" + style.latexname() + "}{"
3736                                 + labelwidthstring + "}\n";
3737                 } else if (style.labeltype == LABEL_BIBLIO) {
3738                         // ale970405
3739                         file += "\\begin{" + style.latexname() + "}{"
3740                                 + bibitemWidthest() + "}\n";
3741                 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3742 #ifdef FANCY_FOOTNOTE_CODE
3743                         if (foot_count < 0) {
3744                                 // flag that footnote[mark][text] should be
3745                                 // used for any footnotes from now on
3746                                 foot_count = 0;
3747                                 foot_this_level = true;
3748                         }
3749 #endif
3750                         file += "\\begin{" + style.latexname() + '}'
3751                                 + style.latexparam() + '\n';
3752                 } else 
3753                         file += "\\begin{" + style.latexname() + '}'
3754                                 + style.latexparam() + '\n';
3755                 texrow.newline();
3756         }
3757         LyXParagraph * par = this;
3758         do {
3759                 par = par->TeXOnePar(file, texrow,
3760                                      foot, foot_texrow, foot_count);
3761
3762                 if (minipage_open && par && !style.isEnvironment() &&
3763                     (par->pextra_type == PEXTRA_MINIPAGE) &&
3764                     par->pextra_start_minipage) {
3765                         file += "\\end{minipage}\n";
3766                         texrow.newline();
3767                         if (par_sep == BufferParams::PARSEP_INDENT) {
3768                                 file += "}\n";
3769                                 texrow.newline();
3770                         }
3771                         minipage_open = false;
3772                 }
3773                 if (par && par->depth > depth) {
3774                         if (textclasslist.Style(GetCurrentTextClass(),
3775                                                 par->layout).isParagraph()
3776                             && !par->table
3777                             && !suffixIs(file, "\n\n")) {
3778                                 // There should be at least one '\n' already
3779                                 // but we need there to be two for Standard 
3780                                 // paragraphs that are depth-increment'ed to be
3781                                 // output correctly.  However, tables can
3782                                 // also be paragraphs so don't adjust them.
3783                                 // ARRae
3784                                 file += '\n';
3785                                 texrow.newline();
3786                         }
3787                         par = par->TeXDeeper(file, texrow,
3788                                              foot, foot_texrow, foot_count);
3789                 }
3790                 if (par && par->layout == layout && par->depth == depth &&
3791                     (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3792                         if (par->pextra_hfill && par->Previous() &&
3793                             (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3794                                 file += "\\hfill{}\n";
3795                                 texrow.newline();
3796                         }
3797                         if (par_sep == BufferParams::PARSEP_INDENT) {
3798                                 file += "{\\setlength\\parindent{0pt}\n";
3799                                 texrow.newline();
3800                         }
3801                         file += "\\begin{minipage}";
3802                         switch(par->pextra_alignment) {
3803                         case MINIPAGE_ALIGN_TOP:
3804                                 file += "[t]";
3805                                 break;
3806                         case MINIPAGE_ALIGN_MIDDLE:
3807                                 file += "[m]";
3808                                 break;
3809                         case MINIPAGE_ALIGN_BOTTOM:
3810                                 file += "[b]";
3811                                 break;
3812                         }
3813                         if (!par->pextra_width.empty()) {
3814                                 file += '{';
3815                                 file += par->pextra_width;
3816                                 file += "}\n";
3817                         } else {
3818                                 //float ib = atof(par->pextra_widthp.c_str())/100;
3819                                 // string can't handle floats at present
3820                                 // so I'll do a conversion by hand knowing that
3821                                 // the limits are 0.0 to 1.0. ARRae.
3822                                 file += '{';
3823                                 switch (par->pextra_widthp.length()) {
3824                                 case 3:
3825                                         file += "1.00";
3826                                         break;
3827                                 case 2:
3828                                         file += "0.";
3829                                         file += par->pextra_widthp;
3830                                         break;
3831                                 case 1:
3832                                         file += "0.0";
3833                                         file += par->pextra_widthp;
3834                                 }
3835                                 file += "\\columnwidth}\n";
3836                         }
3837                         texrow.newline();
3838                         if (par_sep == BufferParams::PARSEP_INDENT) {
3839                                 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3840                                 texrow.newline();
3841                         }
3842                         minipage_open = true;
3843                         minipage_open_depth = par->depth;
3844                 }
3845         } while (par
3846                  && par->layout == layout
3847                  && par->depth == depth
3848                  && par->pextra_type == pextra_type);
3849  
3850         if (style.isEnvironment()) {
3851                 file += "\\end{" + style.latexname() + '}';
3852                 // maybe this should go after the minipage closes?
3853                 if (foot_this_level) {
3854                         if (foot_count >= 1) {
3855                                 if (foot_count > 1) {
3856                                         file += "\\addtocounter{footnote}{-";
3857                                         file += tostr(foot_count - 1);
3858                                         file += '}';
3859                                 }
3860                                 file += foot;
3861                                 texrow += foot_texrow;
3862                                 foot.clear();
3863                                 foot_texrow.reset();
3864                                 foot_count = 0;
3865                         }
3866                 }
3867         }
3868         if (minipage_open && (minipage_open_depth == depth) &&
3869             (!par || par->pextra_start_minipage ||
3870              par->pextra_type != PEXTRA_MINIPAGE)) {
3871                 file += "\\end{minipage}\n";
3872                 texrow.newline();
3873                 if (par_sep == BufferParams::PARSEP_INDENT) {
3874                         file += "}\n";
3875                         texrow.newline();
3876                 }
3877                 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3878                         file += "\\medskip\n\n";
3879                         texrow.newline();
3880                         texrow.newline();
3881                 }
3882                 minipage_open = false;
3883         }
3884         if (eindent_open) {
3885                 file += "\\end{LyXParagraphIndent}\n";
3886                 texrow.newline();
3887         }
3888         if (!(par && (par->pextra_type == PEXTRA_MINIPAGE) 
3889               && par->pextra_hfill)) {
3890                 file += '\n';
3891                 texrow.newline();
3892         }
3893         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3894         return par;  // ale970302
3895 }
3896
3897
3898 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
3899                                          string & foot, TexRow & foot_texrow,
3900                                          int & foot_count)
3901 {
3902         lyxerr[Debug::LATEX] << "TeXFootnote...  " << this << endl;
3903         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3904                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3905                         "No footnote!" << endl;
3906
3907         LyXParagraph * par = this;
3908         LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), 
3909                                                       previous->GetLayout());
3910         
3911         if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3912                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3913                         "Float other than footnote in command"
3914                         " with moving argument is illegal" << endl;
3915         }
3916
3917         if (footnotekind != LyXParagraph::FOOTNOTE
3918             && footnotekind != LyXParagraph::MARGIN
3919             && file.length()
3920             && !suffixIs(file, '\n')) {
3921                 // we need to ensure that real floats like tables and figures
3922                 // have their \begin{} on a new line otherwise we can get
3923                 // incorrect results when using the endfloat.sty package
3924                 // especially if two floats follow one another.  ARRae 981022
3925                 // NOTE: if the file is length 0 it must have just been
3926                 //       written out so we assume it ended with a '\n'
3927                 file += '\n';
3928                 texrow.newline();
3929         }
3930         
3931         BufferParams * params = &current_view->buffer()->params;
3932         bool footer_in_body = true;
3933         switch (footnotekind) {
3934         case LyXParagraph::FOOTNOTE:
3935                 if (style.intitle) {
3936                         file += "\\thanks{\n";
3937                         footer_in_body = false;
3938                 } else {
3939                         if (foot_count == -1) {
3940                                 // we're at depth 0 so we can use:
3941                                 file += "\\footnote{%\n";
3942                                 footer_in_body = false;
3943                         } else {
3944                                 file += "\\footnotemark{}%\n";
3945                                 if (foot_count) {
3946                                         // we only need this when there are
3947                                         // multiple footnotes
3948                                         foot += "\\stepcounter{footnote}";
3949                                 }
3950                                 foot += "\\footnotetext{%\n";
3951                                 foot_texrow.start(this, 0);
3952                                 foot_texrow.newline();
3953                                 ++foot_count;
3954                         }
3955                 }
3956                 break;
3957         case LyXParagraph::MARGIN:
3958                 file += "\\marginpar{\n";
3959                 break;
3960         case LyXParagraph::FIG:
3961                 if (pextra_type == PEXTRA_FLOATFLT
3962                     && (!pextra_width.empty()
3963                         || !pextra_widthp.empty())) {
3964                         char bufr[80];
3965                         if (!pextra_width.empty())
3966                                 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
3967                                         pextra_width.c_str());
3968                         else
3969                                 sprintf(bufr,
3970                                         "\\begin{floatingfigure}{%f\\textwidth}\n",
3971                                         atoi(pextra_widthp.c_str())/100.0);
3972                         file += bufr;
3973                 } else {
3974                         file += "\\begin{figure}";
3975                         if (!params->float_placement.empty()) { 
3976                                 file += '[';
3977                                 file += params->float_placement;
3978                                 file += "]\n";
3979                         } else {
3980                                 file += '\n';
3981                         }
3982                 }
3983                 break;
3984         case LyXParagraph::TAB:
3985                 file += "\\begin{table}";
3986                 if (!params->float_placement.empty()) { 
3987                         file += '[';
3988                         file += params->float_placement;
3989                         file += "]\n";
3990                 } else {
3991                         file += '\n';
3992                 }
3993                 break;
3994         case LyXParagraph::WIDE_FIG:
3995                 file += "\\begin{figure*}";
3996                 if (!params->float_placement.empty()) { 
3997                         file += '[';
3998                         file += params->float_placement;
3999                         file += "]\n";
4000                 } else {
4001                         file += '\n';
4002                 }
4003                 break;
4004         case LyXParagraph::WIDE_TAB:
4005                 file += "\\begin{table*}";
4006                 if (!params->float_placement.empty()) { 
4007                         file += '[';
4008                         file += params->float_placement;
4009                         file += "]\n";
4010                 } else {
4011                         file += '\n';
4012                 }
4013                 break;
4014         case LyXParagraph::ALGORITHM:
4015                 file += "\\begin{algorithm}\n";
4016                 break;
4017         }
4018         texrow.newline();
4019    
4020         if (footnotekind != LyXParagraph::FOOTNOTE
4021             || !footer_in_body) {
4022                 // Process text for all floats except footnotes in body
4023                 do {
4024                         LyXLayout const & style =
4025                                 textclasslist.Style(GetCurrentTextClass(),
4026                                                     par->layout);
4027                         if (par->IsDummy())
4028                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4029                                        << endl;
4030                         if (style.isEnvironment()
4031                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4032                                 // Allows the use of minipages within float
4033                                 // environments. Shouldn't be circular because
4034                                 // we don't support footnotes inside
4035                                 // floats (yet). ARRae
4036                                 par = par->TeXEnvironment(file, texrow,
4037                                                           foot, foot_texrow,
4038                                                           foot_count);
4039                         } else {
4040                                 par = par->TeXOnePar(file, texrow,
4041                                                      foot, foot_texrow,
4042                                                      foot_count);
4043                         }
4044                         
4045                         if (par && !par->IsDummy() && par->depth > depth) {
4046                                 par = par->TeXDeeper(file, texrow,
4047                                                      foot, foot_texrow,
4048                                                      foot_count);
4049                         }
4050                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4051         } else {
4052                 // process footnotes > depth 0 or in environments separately
4053                 // NOTE: Currently don't support footnotes within footnotes
4054                 //       even though that is possible using the \footnotemark
4055                 string dummy;
4056                 TexRow dummy_texrow;
4057                 int dummy_count = 0;
4058                 do {
4059                         LyXLayout const & style =
4060                                 textclasslist.Style(GetCurrentTextClass(),
4061                                                     par->layout);
4062                         if (par->IsDummy())
4063                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4064                                        << endl;
4065                         if (style.isEnvironment()
4066                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4067                                 // Allows the use of minipages within float
4068                                 // environments. Shouldn't be circular because
4069                                 // we don't support footnotes inside
4070                                 // floats (yet). ARRae
4071                                 par = par->TeXEnvironment(foot, foot_texrow,
4072                                                           dummy, dummy_texrow,
4073                                                           dummy_count);
4074                         } else {
4075                                 par = par->TeXOnePar(foot, foot_texrow,
4076                                                      dummy, dummy_texrow,
4077                                                      dummy_count);
4078                         }
4079
4080                         if (par && !par->IsDummy() && par->depth > depth) {
4081                                 par = par->TeXDeeper(foot, foot_texrow,
4082                                                      dummy, dummy_texrow,
4083                                                      dummy_count);
4084                         }
4085                 } while (par
4086                          && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4087                 if (dummy_count) {
4088                         lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4089                                 "Footnote in a Footnote -- not supported"
4090                                << endl;
4091                 }
4092         }
4093
4094         switch (footnotekind) {
4095         case LyXParagraph::FOOTNOTE:
4096                 if (footer_in_body) {
4097                         // This helps tell which of the multiple
4098                         // footnotetexts an error was in.
4099                         foot += "}%\n";
4100                         foot_texrow.newline();
4101                 } else {
4102                         file += '}';
4103                 }
4104                 break;
4105         case LyXParagraph::MARGIN:
4106                 file += '}';
4107                 break;
4108         case LyXParagraph::FIG:
4109                 if (pextra_type == PEXTRA_FLOATFLT
4110                     && (!pextra_width.empty()
4111                         || !pextra_widthp.empty()))
4112                         file += "\\end{floatingfigure}";
4113                 else
4114                         file += "\\end{figure}";
4115                 break;
4116         case LyXParagraph::TAB:
4117                 file += "\\end{table}";
4118                 break;
4119         case LyXParagraph::WIDE_FIG:
4120                 file += "\\end{figure*}";
4121                 break;
4122         case LyXParagraph::WIDE_TAB:
4123                 file += "\\end{table*}";
4124                 break;
4125         case LyXParagraph::ALGORITHM:
4126                 file += "\\end{algorithm}";
4127                 break;
4128         }
4129
4130         if (footnotekind != LyXParagraph::FOOTNOTE
4131             && footnotekind != LyXParagraph::MARGIN) {
4132                 // we need to ensure that real floats like tables and figures
4133                 // have their \end{} on a line of their own otherwise we can
4134                 // get incorrect results when using the endfloat.sty package.
4135                 file += "\n";
4136                 texrow.newline();
4137         }
4138
4139         lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4140         return par;
4141 }
4142
4143
4144 void LyXParagraph::SetPExtraType(int type, char const * width,
4145                                  char const * widthp)
4146 {
4147         pextra_type = type;
4148         pextra_width = width;
4149         pextra_widthp = widthp;
4150
4151         if (textclasslist.Style(GetCurrentTextClass(), 
4152                                 layout).isEnvironment()) {
4153                 LyXParagraph
4154                         * par = this,
4155                         * ppar = par;
4156
4157                 while (par && (par->layout == layout)
4158                        && (par->depth == depth)) {
4159                         ppar = par;
4160                         par = par->Previous();
4161                         if (par)
4162                                 par = par->FirstPhysicalPar();
4163                         while (par && par->depth > depth) {
4164                                 par = par->Previous();
4165                                 if (par)
4166                                         par = par->FirstPhysicalPar();
4167                         }
4168                 }
4169                 par = ppar;
4170                 while (par && (par->layout == layout)
4171                        && (par->depth == depth)) {
4172                         par->pextra_type = type;
4173                         par->pextra_width = width;
4174                         par->pextra_widthp = widthp;
4175                         par = par->NextAfterFootnote();
4176                         if (par && (par->depth > depth))
4177                                 par->SetPExtraType(type, width, widthp);
4178                         while (par && ((par->depth > depth) || par->IsDummy()))
4179                                 par = par->NextAfterFootnote();
4180                 }
4181         }
4182 }
4183
4184
4185 void LyXParagraph::UnsetPExtraType()
4186 {
4187         if (pextra_type == PEXTRA_NONE)
4188                 return;
4189     
4190         pextra_type = PEXTRA_NONE;
4191         pextra_width.clear();
4192         pextra_widthp.clear();
4193
4194         if (textclasslist.Style(GetCurrentTextClass(), 
4195                                 layout).isEnvironment()) {
4196                 LyXParagraph
4197                         * par = this,
4198                         * ppar = par;
4199
4200                 while (par && (par->layout == layout)
4201                        && (par->depth == depth)) {
4202                         ppar = par;
4203                         par = par->Previous();
4204                         if (par)
4205                                 par = par->FirstPhysicalPar();
4206                         while (par && par->depth > depth) {
4207                                 par = par->Previous();
4208                                 if (par)
4209                                         par = par->FirstPhysicalPar();
4210                         }
4211                 }
4212                 par = ppar;
4213                 while (par && (par->layout == layout)
4214                        && (par->depth == depth)) {
4215                         par->pextra_type = PEXTRA_NONE;
4216                         par->pextra_width.clear();
4217                         par->pextra_widthp.clear();
4218                         par = par->NextAfterFootnote();
4219                         if (par && (par->depth > depth))
4220                                 par->UnsetPExtraType();
4221                         while (par && ((par->depth > depth) || par->IsDummy()))
4222                                 par = par->NextAfterFootnote();
4223                 }
4224         }
4225 }
4226
4227
4228 bool LyXParagraph::IsHfill(size_type pos) const
4229 {
4230         return IsHfillChar(GetChar(pos));
4231 }
4232
4233
4234 bool LyXParagraph::IsInset(size_type pos) const
4235 {
4236         return IsInsetChar(GetChar(pos));
4237 }
4238
4239
4240 bool LyXParagraph::IsFloat(size_type pos) const
4241 {
4242         return IsFloatChar(GetChar(pos));
4243 }
4244
4245
4246 bool LyXParagraph::IsNewline(size_type pos) const
4247 {
4248         bool tmp = false;
4249         if (pos >= 0)
4250                 tmp = IsNewlineChar(GetChar(pos));
4251         return tmp;
4252 }
4253
4254
4255 bool LyXParagraph::IsSeparator(size_type pos) const
4256 {
4257         return IsSeparatorChar(GetChar(pos));
4258 }
4259
4260
4261 bool LyXParagraph::IsLineSeparator(size_type pos) const
4262 {
4263         return IsLineSeparatorChar(GetChar(pos));
4264 }
4265
4266
4267 bool LyXParagraph::IsKomma(size_type pos) const
4268 {
4269         return IsKommaChar(GetChar(pos));
4270 }
4271
4272
4273 /// Used by the spellchecker
4274 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4275 {
4276         unsigned char c = GetChar(pos);
4277         if (IsLetterChar(c))
4278                 return true;
4279         // '\0' is not a letter, allthough every string contains "" (below)
4280         if( c == '\0')
4281                 return false;
4282         // We want to pass the ' and escape chars to ispell
4283         string extra = lyxrc->isp_esc_chars + '\'';
4284         char ch[2];
4285         ch[0] = c;
4286         ch[1] = 0;
4287         return contains(extra, ch);
4288 }
4289  
4290  
4291 bool LyXParagraph::IsWord(size_type pos ) const
4292 {
4293         return IsWordChar(GetChar(pos)) ;
4294 }